1. Introduction

This automated reported is intended to serve as a template for a **coverage and gaps analysis*. It provides examples of the analyses necessary to identify populations in need who are not currently covered by humanitarian action and provide recommendations on how partners may best reach them. Coverage and gaps analyses should be coordinated with monitoring and evaluation (M&E) activities, and opportunities where Information Management and M&E may reinforce each other are mentioned below, in the relevant sections.

Coverage and gaps analyses are key documents, but are also rarely taken into account during operational planning or referenced during revisions of major strategic documents, such as Humanitarian Response Plans (HRPs). Neither are they mentioned in OCHA’s HRP guidance.

Given that needs always grossly outweigh available funding, it still remains an industry-wide challenge to respond adequately to gaps in coverage and reallocate resources accordingly. Too often, once committed to a course of action, clusters and their humanitarian partners do not re-examine or re-evaluate their interventions. The analyses shown below are not complicated and they have all been performed by a single analyst; yet, this type of report remains exceedingly rare.

A note on the data

  • Most of the data originates from the Education, Health, Nutrition, Protection and WASH Clusters, from May to October 2019 – and any conclusions or analysis are bounded by this time period and illustrative of the response as it was in November 2019. Partner data has been anonymised. Other data originate from the census dataset of Venezuela that was maintained by UNICEF. Unlike the document of 5W reporting and cleaning, we will not be exploring the cleaning process. But the source code of each chunk will be displayed when the Code button is clicked.
# reading and cleaning -- you really should break it into parts
ven1 <- read_csv("consolidation 191209 1636.csv") %>% 
  clean_names() %>% 
  # removing unused columns
  select(-c(codigodeestablecimientoocentro, loc_id, hrp_sitre_p_indicator, 
            tipoderespuesta, comentarios, coordeadas_gps_x, coordeadas_gps_y,
            fechade_inicio, fecha_previstade_finalizacion)) %>% 
  # renaming unwieldy columns 
  rename(ubicacion          = comunidadonombredelestablecimiento_centro, 
         sector             = sector_areade_responsabiliad,
         beneficiarios_meta = beneficiarios_meta_numerodepersonas,
         estatus            = estatusdeprogramacion) %>% 
      # mutating the date to the right format
  mutate(month = as.factor(recode(month,
                        `4` = "30/04/2019",
                        `5` = "31/05/2019",
                        `6` = "30/06/2019",
                        `7` = "31/07/2019",
                        `8` = "31/08/2019",
                        `9` = "30/09/2019",
                        `10` = "31/10/2019"))) %>% 
  mutate(month = as.Date(month %>% strptime(., format = "%d/%m/%Y"))) %>% 
  mutate(org_lider = coalesce(org_lider, org_implementadora)) %>% 
  # correcting sector names
  mutate(sector = str_replace_all(sector, c(
    "Agua_saneamiento_higiene"            = "WASH",
    "educacion"                           = "Educacion",
    "Nutricion"                           = "Nutricion",
    "protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
    "Protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
    "Protección_Violencia_Género"         = "Proteccion_GBV"))) %>% 
  # renaming beneficiary disaggregation columns 
  rename(f_0_18 = f_18,
         m_0_18 = m_18,
         f_18plus = f_18_2,
         m_18plus = m_18_2) %>% 
  mutate(estado    = rm_accent(str_to_upper(estado)), 
         municipio = rm_accent(str_to_upper(municipio)),
         parroquia = rm_accent(str_to_upper(parroquia)),
         ubicacion = rm_accent(str_to_upper(ubicacion)),
         actividad = rm_accent(str_to_upper(actividad)),
         categoria = rm_accent(str_to_upper(categoriadeactividad))) %>% 
  # recoding the estatus column 
  mutate(estatus = str_replace_all(estatus, 
                  c("En ejecucion" = "ejecucion", 
                    "en ejecución" = "ejecucion", 
                    "en Ejecución" = "ejecucion",
                    "En ejecución" = "ejecucion",
                    "En Ejecución" = "ejecucion",
                    "Enejecución"  = "ejecucion",
                    "43741"        = "ejecucion",
                    "finalizada" = "finalizada",
                    "Finalizada" = "finalizada",
                    "Planeada" = "planeada",
                    "planeada con financiamiento" = "planeada",
                    "planeada sin financiamiento" = "planeada"))) %>% 
  replace_na(list(estatus = "ejecucion")) %>% 
  # removing all planned activities 
  filter(estatus != "planeada") %>% 
  filter(str_detect(pcode3, "^VE")) %>% # decide if you want to do this here or later
  select(-c(23:92))

# I'm kinda doubting the use of u_ben, ya I think take it out? since you're only using it once
# Am I just making these out of habit? I could make them inside the 
# code chunk for parr, but maybe I can find some justification for their existence, 
# maybe the disaggregations? 

# Vaccination activities filtered out
u_ben <- ven1 %>% 
  pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(categoriadeactividad != "Vacunacion") %>% 
  filter(beneficiarios != 0) %>% 
  group_by(ubicacion, desagregacion) %>% 
  slice(which.max(beneficiarios)) %>% 
  ungroup()

act_ben <- ven1 %>% 
  pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>% 
  filter(beneficiarios != 0) %>% 
  group_by(ubicacion, desagregacion, actividad) %>% 
  slice(which.max(beneficiarios)) %>% 
  ungroup() %>% 
  mutate(sector = ifelse(str_detect(sector, "Proteccion_GBV|Proteccion_General|Proteccion_NNA"), 
                         "Proteccion", sector))

# rbind(sum(u_ben$beneficiarios), 
#       sum(act_ben$beneficiarios), 
#       sum(u_ben$beneficiarios) - sum(act_ben$beneficiarios))
# I think this is a gigantic chunk -- cannot decide if I would rather have less things in the 
# environment or if I want more readable chunks. The benefit here I guess is that if I want to change something, I just have to come to this chunk

parr <- u_ben %>% 
  group_by(pcode3) %>% 
  summarise(beneficiarios = sum(beneficiarios)) %>% 
  ungroup() %>% 
  # count of organisations per pcode3
  left_join(act_ben %>% 
             # filter(categoria != "Vacunacion") %>%
             group_by(pcode3) %>% 
             summarise(org_count = n_distinct(org_implementadora))) %>% 
  # getting beneficiary frequencies, sector count and maximum multi-sector beneficiaries
  left_join(act_ben %>%
  # vaccination filtered out  
   filter(categoriadeactividad != "Vacunacion") %>% 
             group_by(ubicacion, desagregacion, sector) %>% 
                 slice(which.max(beneficiarios)) %>% 
                 ungroup() %>%
                 group_by(ubicacion, sector, pcode3) %>% 
                 pivot_wider(names_from = sector, values_from = beneficiarios) %>% 
                 replace_na(list(Nutricion = 0, Educacion = 0, WASH = 0, Salud = 0,
                                 Seguridad_Alimentaria = 0, Proteccion = 0)) %>%
             group_by(pcode3, desagregacion) %>% 
             summarise(nutricion_ben   = sum(Nutricion),
                       proteccion_ben  = sum(Proteccion),
                       wash_ben        = sum(WASH),
                       salud_ben       = sum(Salud),
                       educacion_ben   = sum(Educacion),
                       sa_ben          = sum(Seguridad_Alimentaria), .groups = "drop") %>% 
             mutate(ben_freq    = nutricion_ben + proteccion_ben + wash_ben + salud_ben +
                                 educacion_ben + sa_ben,
                    sec_ben_max = pmax(nutricion_ben, proteccion_ben, wash_ben, 
                                      salud_ben, educacion_ben, sa_ben),
                    ms_ben_max  = ifelse(sec_ben_max >= ben_freq - sec_ben_max, 
                                        ben_freq - sec_ben_max, 
                                        sec_ben_max)) %>% 
             group_by(pcode3) %>% 
             summarise(nutricion_ben  = sum(nutricion_ben),
                       proteccion_ben = sum(proteccion_ben),
                       wash_ben       = sum(wash_ben),
                       salud_ben      = sum(salud_ben),
                       educacion_ben  = sum(educacion_ben),
                       sa_ben         = sum(sa_ben),
                       ben_freq   = sum(ben_freq),
                       sec_ben_max    = sum(sec_ben_max),
                       ms_ben_max = sum(ms_ben_max)) %>% 
             mutate(sector_count = rowSums(select(., ends_with("_ben")) != 0))) %>%  
  filter(str_detect(pcode3, "^VE")) %>% 
  # right_join to the census data
  right_join(read_excel("census data 20191122.xlsx", sheet = "data") %>% 
        clean_names() %>% 
        # selecting variables and renaming them with select
        select(estado, pcode1, municipio, pcode2, parroquia, pcode3, 
               fo = field_office,
               poblacion_2019 = x_2019_poblacion_parroquial_total,
               hogares_2011 = numero_de_hogares, 
               ham_2019_ambitos_ge, 
               percent_pobre = ham_2019_xx_pobreza_env_por_parroquia, 
               pob_pobre = ham_2019_xx_poblacion_pobre_por_parroquia, 
               poblacion_total_2011,
               poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos,
               poblacion_de_18_anos_y_mas, 
               percent_urbana = poblacion_urbana_percent, 
               area_km2, 
               densidad_ppl_km2 = densidad_poblacional_ppl_km2,
               matricula_2017_educacion_inicial, matricula_2017_educacion_primaria, 
               matricula_2017_educacion_media, razon_de_dependencia_total,
               razon_de_dependencia_de_menores_de_15_anos, 
               percent_sin_agua_segura = x_abast_agua2_percent_sin_agua_segura,
               percent_sin_saneamiento_mejorado =
                 x_saneamiento_percent_sin_saneamiento_mejorado,
               percent_analfabeto = percent_poblacion_10_anos_y_mas_analfabeta,
               promedio_de_personas_por_vivienda,
               percent_hogares_jefatura_femenina = percent_de_hogares_con_jefatura_femenina,
               percent_sin_servicio_electrico =
                 servicio_electrico_percent_no_tiene_servicio_electrico,
               ham_2019_x_violencia_envelope, ham_2019_x_mortalidad_y_salud_envelope, 
               ham_2019_x_pobreza_envelope, promedio_de_edad) %>% 
        mutate(estado     = rm_accent(str_to_upper(estado)), # just to make sure 
               municipio  = rm_accent(str_to_upper(municipio)),
               parroquia  = rm_accent(str_to_upper(parroquia))) %>% 
        # creating new disaggregation variables 
        mutate(pob_menor_de_18 = (poblacion_infantil_menor_de_12_anos +
                                 poblacion_adolescentes_de_12_a_17_anos) /poblacion_total_2011 *
                                 poblacion_2019, 
               pob_18_y_mas    = poblacion_de_18_anos_y_mas / poblacion_total_2011 * poblacion_2019, 
               hogares_2019    = hogares_2011 * poblacion_2019 / poblacion_total_2011, 
               matricula_total = matricula_2017_educacion_inicial + 
                                 matricula_2017_educacion_primaria + 
                                 matricula_2017_educacion_media) %>% 
        # dividing columns by 100 so that they're between 0 and 1
        mutate_at(vars(percent_analfabeto, percent_sin_servicio_electrico, 
                       percent_sin_agua_segura,
                       percent_sin_saneamiento_mejorado,
                       percent_hogares_jefatura_femenina, percent_urbana,
                       razon_de_dependencia_total), ~(. / 100)) %>% 
        # mutating new columns with populations
        mutate(pob_analfabeto               = percent_analfabeto * poblacion_2019,
               pob_sin_agua_segura          = percent_sin_agua_segura * poblacion_2019, 
               pob_sin_servicio_electrico   = percent_sin_servicio_electrico * poblacion_2019,
               pob_sin_saneamiento_mejorado = percent_sin_saneamiento_mejorado * poblacion_2019,
               pob_urbana                   = percent_urbana * poblacion_2019) %>% 
        select(-c(matricula_2017_educacion_inicial, matricula_2017_educacion_primaria, 
               matricula_2017_educacion_media, poblacion_total_2011, hogares_2011,
               poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos, 
               poblacion_de_18_anos_y_mas)),
            by = "pcode3") %>% 
  # mutating new variables and making sure NAs become 0s 
  mutate(beneficiarios  = ifelse(is.na(beneficiarios), 0, beneficiarios),
         org_count      = ifelse(is.na(org_count), 0, org_count),
         sector_count   = ifelse(is.na(sector_count), 0, sector_count), 
         educacion_ben  = ifelse(is.na(educacion_ben), 0, educacion_ben),
         nutricion_ben  = ifelse(is.na(nutricion_ben), 0, nutricion_ben),
         proteccion_ben = ifelse(is.na(proteccion_ben), 0, proteccion_ben),
         salud_ben      = ifelse(is.na(salud_ben), 0, salud_ben),
         sa_ben         = ifelse(is.na(sa_ben), 0, sa_ben),
         wash_ben       = ifelse(is.na(wash_ben), 0, wash_ben),
         ms_ben_max     = ifelse(is.na(ms_ben_max), 0, ms_ben_max),
         ben_freq       = ifelse(is.na(ben_freq), 0, ben_freq),
         not_reached            = pob_pobre - beneficiarios,
         coverage_percent       = beneficiarios / poblacion_2019,
         coverage_pobre_percent = beneficiarios / pob_pobre,
         percent_total_ben      = beneficiarios / sum(beneficiarios),
         multisector_percent    = ms_ben_max / ben_freq, 
         org_present            = ifelse(beneficiarios > 0, TRUE, FALSE),
         pob_pobre_score     = rescale(pob_pobre, to = c(0,1)), 
         percent_pobre_score = rescale(percent_pobre, to = c(0,1)), 
         poverty_score       = (pob_pobre_score + percent_pobre_score) / 2)

# taking a subset of parr to only get parrishes where the number of beneficiaries does not exceed the number of poor persons

parr0 <- parr %>% 
  filter(not_reached >= 1) %>% 
  mutate(gap_score = (rescale(not_reached, to = c(0,1)) + percent_pobre_score) / 2)

2. Summary of coverage and gaps

2a. Map of parrishes by gaps

# parrishes with negative poor persons are recoded as "0" so they won't mess up the scale
# even though this means that their tooltips are dropped 

gaps_map <- parr %>% 
  right_join(pcode3_shape, by = "pcode3") %>% 
  st_as_sf() %>% 
  mutate(not_reached = ifelse(not_reached < 0.1, 0, not_reached)) %>% 
  mutate(not_reached = round(not_reached, digits = 0)) %>%
  mutate_at(vars(percent_pobre, percent_urbana), ~(round(., digits = 2))) %>% 
  ggplot() +
  geom_sf(aes(fill = not_reached,
              text = paste0(parroquia,",", "\n", 
                           municipio, ",", "\n",
                           estado, "\n", 
                           "not reached: ", not_reached, "\n",
                           "org count: ", org_count, "\n",
                           "poverty incidence: ", percent_pobre, "\n",
                           "percent urban: ", percent_urbana)),
          size = 0.1) +
  scale_fill_viridis_c(option = "turbo", trans = "log10") +
  theme_void() +
  theme(legend.title = element_text(size = 7),
        legend.text = element_text(size = 7),
        plot.title = element_text(size = 11)) +
  labs(fill = "Poor persons \nnot reached") +
  ggtitle("Map of parrishes by gaps in population reached")

# so are you saying that if I change the fill to viridis in the later plot, I can use hoveron = fill?
# no you can't. 
ggplotly(gaps_map, tooltip = c("text")) %>%
  layout(showlegend = TRUE, legend = list(font = list(size = 6))) %>% 
  style(hoveron = "fill") %>% 
  layout(title = list(text = paste0("Map of parrishes by number poor persons not reached",
                                    "<br>",
                                    "<sup>",
                                    "mouse over for details; drag and click to select and zoom; double-click legend select/deselect","</sup>")))

Nationwide, 11,633,901 poor persons have not been covered by response activities – this means that 94.6% all the poor persons in the country have yet to be reached. It is this population and its distribution and the characteristics of its sub-groups that is the main concern of this analysis.


2b. Grouping parrishes by coverage

As a starting point, all 1109 parrishes (admin level 3) have been split into three groups – over, where the number of unique beneficiaries reached exceeds the number of poor persons in that parrish; under, where the coverage is less than the number of poor persons; and no coverage, comprising a total of 530 parrishes, where no activities have occurred.

However, it should be noted that a total of 11,633,901 poor persons reside in the 530 parrishes that have not been reached, this is only 25% of the 11,170,010 poor persons not covered by response activities. This indicates that

  1. there is much room to expand in the parrishes where we are already present and that
  2. sparely populated, remote and, consequently, poorer parrishes have, so far, been left out of the response.
parr %>% 
  mutate(coverage_type = case_when(not_reached <= 0 ~ "over",
                                   not_reached > 0 & beneficiarios >= 1 ~ "under", 
                                   beneficiarios == 0 ~ "no_coverage")) %>% 
  group_by(coverage_type) %>% 
  summarise(parroquias = n(),
            beneficiarios = sum(beneficiarios),
            not_reached = sum(not_reached), 
            avg_org_count = mean(org_count),
            percent_pobre = round(sum(pob_pobre) / sum(poblacion_2019) * 100, digits = 1),
            percent_urbana = round(sum(pob_urbana) /sum(poblacion_2019) * 100, digits = 1),
            percent_wo_safe_water = round(sum(pob_sin_agua_segura) / sum(poblacion_2019) * 100, digits = 1),
            percent_wo_improved_sanitation = round(sum(pob_sin_saneamiento_mejorado)/
              sum(poblacion_2019)  * 100, digits = 1),
            percent_illiterate = round(sum(pob_analfabeto) / sum(poblacion_2019) * 100, digits = 1),
            avg_sector_count = mean(sector_count)) %>% 
  pivot_longer(cols = -coverage_type, names_to = "variable") %>% 
  pivot_wider(names_from = coverage_type, values_from = value) %>% 
  
  relocate(no_coverage, .after = under) %>% 
  pander(big.mark = ",", caption = "Parrishes characteristics by coverage type", style = "rmarkdown")
Parrishes characteristics by coverage type
variable over under no_coverage
parroquias 11 568 530
beneficiarios 658,812 658,257 0
not_reached -463,891 8,838,144 2,795,757
avg_org_count 7.818 2.718 0
percent_pobre 20.3 37.4 46
percent_urbana 99.5 93 67.9
percent_wo_safe_water 2 13.2 23
percent_wo_improved_sanitation 1 7 18.1
percent_illiterate 2 4.5 8.5
avg_sector_count 4 1.764 0

We note that the 11 parrishes in the over category are much less poor and much more urban despite having 50% of all beneficiaries. These parrishes are shown in the table below. And, as can be seen from not_reached, the number beneficiaries in the over category has greatly exceeded the number of poor persons.


2c. Top parrishes in terms of coverage

The 11 parrishes below (from the over category) will largely be excluded in the remainder of this report as it is clear that no further resources should be allocated to them:

parr %>% 
  mutate(coverage_type = case_when(not_reached <= 0 ~ "over",
                                   not_reached > 0 & beneficiarios >= 1 ~ "under", 
                                   beneficiarios == 0 ~ "not_reached")) %>%  
  filter(coverage_type == "over") %>% 
  select(estado, municipio, estado, parroquia, beneficiarios, pob_pobre) %>%
  mutate(coverage_percent = beneficiarios / pob_pobre * 100) %>% 
  arrange(desc(beneficiarios)) %>% 
  pander(big.mark = ",", caption = "Top 11 parrishes by coverage", style = "rmarkdown")
Top 11 parrishes by coverage
estado municipio parroquia beneficiarios pob_pobre coverage_percent
DISTRITO CAPITAL LIBERTADOR ALTAGRACIA 321,597 6,244 5,151
MIRANDA SUCRE PETARE 178,814 82,058 217.9
BOLIVAR CARONI ONCE DE ABRIL 69,332 54,118 128.1
BOLIVAR HERES CATEDRAL 32,177 14,336 224.4
BOLIVAR HERES VISTA HERMOSA 18,477 13,919 132.7
MIRANDA CHACAO CHACAO 13,780 5,481 251.4
TACHIRA ANDRES BELLO CAPITAL CORDERO 8,596 7,766 110.7
MIRANDA SUCRE LEONCIO MARTINEZ 6,834 4,792 142.6
CARABOBO VALENCIA URBANA CANDELARIA 5,043 4,589 109.9
TACHIRA BOLIVAR GENERAL JUAN VICENTE GOMEZ 2,253 362.1 622.3
DELTA AMACURO TUCUPITA SAN JOSE 1,909 1,256 152

As a note, it is likely that partners have reported activities which occurred in other parts of the capital in Altagracia, as the total number of benefificaries reached in the whole of Distrito Capital is only 415,301. It is necessary to check back with partners about this; nevertheless, this is the information we have on hand.


3. Geographical analysis of Gaps

3a. Barplot of coverage and gaps by state

# ref for printing state_ord. I'm really not sure how to extract all the variables as a list
# parr0 %>% 
#   group_by(estado) %>% 
#   summarise(not_reached = sum(not_reached)) %>% 
#   arrange(desc(not_reached)) %>% 
#   select(estado) %>% as.list(as.data.frame(t(.)))

state_ord <- c("ZULIA", "LARA", "CARABOBO", "MIRANDA", "ANZOATEGUI", "ARAGUA", "BOLIVAR",
               "PORTUGUESA", "SUCRE", "GUARICO", "FALCON", "MONAGAS", "BARINAS", "MERIDA",
               "TACHIRA", "TRUJILLO", "YARACUY", "APURE", "DISTRITO CAPITAL", "NUEVA ESPARTA",
               "COJEDES", "VARGAS", "DELTA AMACURO", "AMAZONAS")
  
stack_text <- parr0 %>% 
  group_by(estado) %>% 
  summarise(beneficiarios = sum(beneficiarios),
            total = sum(pob_pobre)) %>% 
  mutate(percent_reached = round(beneficiarios / total * 100, digits = 2)) %>% 
  arrange(desc(total)) 

state_stack <- parr0 %>% 
  select(estado, beneficiarios, not_reached) %>% 
  group_by(estado) %>%
  summarise(beneficiarios = round(sum(beneficiarios), digits = 0), 
            not_reached = round(sum(not_reached), digits = 0)) %>% 
  pivot_longer(c(beneficiarios, not_reached),
               names_to = "pob_type", values_to = "total") %>% 
  
  ggplot(aes(x = estado, y = total)) +
  geom_col(aes(fill = pob_type)) +
  scale_y_continuous(label = comma) +
  scale_x_discrete(limits = state_ord) +
  scale_fill_manual(values = c("coral", "royalblue")) +
  geom_text(data = stack_text, aes(y = 20000,
                                   label = percent_reached), 
            size = 2, fontface = "bold", colour = "white") +
  theme(axis.text.x  = element_text(angle = 45, hjust = 1, size = 6.5),
        axis.text.y  = element_text(size = 5),
        axis.title.y = element_text(size = 9),
        plot.title   = element_text(size = 11)) +
  xlab("") + ylab("Number of poor persons") + 
  labs(fill = "",
       title = "Barplot of poor persons by state by reached/not reached")

ggplotly(state_stack) %>% 
  layout(legend = list(font = list(size = 7))) %>% 
  config(displayModeBar = FALSE) %>% 
  layout(title = list(text = paste0(
    "Barplot of poor persons by state by reached/not reached",
                                    "<br>",
                                    "<sup>",
                                    "mouse over for details","</sup>")))

87% of all beneficiaries are from the states of Distrito Capital, Miranda, Tachira, Bolivar and Zulia, largely corresponding to the locations of UNICEF offices. These states, with the addition of Delta Amacuro, are also where the highest percentages of poor persons have been reached, indicating some overallocation has occurred.

Carabobo has the lowest percentage of its poor population covered. On average, after the exclusion of the top 11 parrishes, 10.5% of poor persons have been reached countrywide.

Whilst there are many poor persons yet to be reached in states where we have relatively high coverage, there is a need to ensure that our operational footprint and the consequent resources allocated are equitable – the crisis in Venezuela is nationwide, and unlike an earthquake or a typhoon where there is an epicentre or a stormpath, there is no programmatic rationale to only focus on a few areas.

Let us now move down to a lower level of granularity as state-level analysis is still too superficial. Parrishes will be the main administrative unit of reference in this analysis. Unlike in the 5W cleaning and reporting document, where we focused on municipalities to display achievements for external audiences, greater precision is needed for a coverage and gaps analysis.


3b. Scatterplot of gaps by parrish

From the scatterplot below – where each point is a parrish – we see that there is great variation both in the number of poor persons not covered (size and x-axis) as well as how concentrated they are in a given parrish (y-axis, poverty incidence); both these factors weigh heavily in programming strategies as well as in the ease of beneficiary selection.

The greatest numbers of not reached are found in parrishes between the ranges of poor persons: 10,000-100,000 and poverty incidence: 0.25-0.50 (marked by the yellow box); however, these parrishes also have a much higher than average number of organisations present (more red). This means that operational barriers are much lower in accessing these populations than the parrishes in light blue found in the middle of the plot.

parrplot <- parr0 %>% 
  mutate_at(vars(pob_pobre, not_reached, org_count), ~(round(.))) %>% 
  mutate(percent_pobre = round(percent_pobre, digits = 2))%>% 
  ggplot(aes(x = not_reached, y = percent_pobre, 
             colour = org_count, 
             text = paste0(parroquia, ", ", estado))) +
   geom_rect(aes(xmin = 10000, xmax = 100000, ymin = 0.25, ymax = 0.50),
            fill = "transparent", colour = "gold", size = 0.2) +
  geom_jitter(aes(size = not_reached), alpha = 0.75) +
  scale_colour_gradientn(
    colours = c("cornflowerblue", "tomato", "firebrick")) +
  scale_x_continuous(trans = "log10", labels = comma) + 
  scale_size_continuous(range = c(0.3, 5)) +
  xlab("Not covered poor") + ylab("Poverty incidence") +
  labs(colour = "Number of \norganisations", 
       title = "Scatterplot of parrishes by poor persons not covered and poverty incidence") +
  theme(legend.title = element_text(size = 7),
        legend.text = element_text(size = 7),
        plot.title = element_text(size = 11),
        axis.title = element_text(size = 8.5)) 
  

ggplotly(parrplot, tooltip = c("y", "x", "size", "text", "colour")) %>% 
           layout(showlegend = TRUE, legend = list(font = list(size = 7))) %>%
           config(displayModeBar = FALSE) %>% 
  layout(title = list(text = paste0(
    "Scatterplot of parrishes by number poor persons not reached and poverty incidence",
                                    "<br>",
                                    "<sup>",
                                    "size: number of poor persons not reached; colour: number of organisations present; drag and click to select and zoom","</sup>")))

For agencies truly unable to expand outside their current footprints, there are still many beneficiaries who are not covered or – as we will discuss in the next part – have only been reached with the interventions of one sector.


4. Multi-sector programming

Humanitarian emergencies are multidimensional and do not affect only one aspect of the lives of affected persons. Phenomena such as displacement or food insecurity result from the complex interplay of numerous underlying factors and the shocks and stresses of the hazard. The response to this, multi-sector or integrated programming, consists of implementing layers of individual, household and community-level interventions to comprehensively meet the needs of the target population. It is often held up as a gold standard in strategy documents and humanitarian standards, but rarely achieved in practice.

4a. Summary table of multi-sector coverage

However, just because two Clusters operate in the same area do not mean their beneficiaries coincide. As an estimate, we calculated a theoretical maximum number of multi-sector beneficiaries per parrish, expressed below as multi_sector_ben (exact calculation and explanation in the code chunk below). Parrishes have then been split into groups based on the number of sectors present within them:

# calculation for multi-sector beneficiaries. 
# Basically, beneficiaries per parrish are aggregated into 
# sector subtotals and a beneficiary frequency total.  
# The maximum value of the sector subtotals is compared against the beneficiary frequency total, 
# if the maximum value is equal to the frequency total, then there is only one sector,
# if the maximum value is less than the frequency total, 
# the difference between the two (or the sum of all other sector subtotals) 
# becomes the theoretical maximum number of multisector beneficiaries.

# Performing this calculation at admin level 3 makes sense as a parrish is small enough
# that there it is realistic to assume that overlaps in beneficiaries between sectors exist --
# i.e. that females under 18 in a parrish who are beneficiaries of nutrition 
# and females under 18 in that same parrish who are beneficiaries of WASH are the same people. 

# Although I do feel this calculation to be very charitable 
# We can't really do much more unless there is a beneficiary register. 
# The real number of multisector beneficiaries is likely MUCH LOWER 
# but that can only be verified through sampled large-scale post-distribution/post-intervention monitoring,
# which is extremely rare. 
# I actually could have raised this with the third-party monitors that UNICEF, 
# so it's an oversight on my part as well.

 act_ben %>%
  # vaccination filtered out  
   filter(categoriadeactividad != "Vacunacion") %>%
                 group_by(ubicacion, sector, pcode3) %>% 
                 pivot_wider(names_from = sector, values_from = beneficiarios) %>% 
                 replace_na(list(Nutricion = 0, Educacion = 0, WASH = 0, Salud = 0,
                                 Seguridad_Alimentaria = 0, Proteccion = 0)) %>%
             group_by(pcode3, desagregacion) %>% 
             summarise(nutricion_ben   = sum(Nutricion),
                       proteccion_ben  = sum(Proteccion),
                       wash_ben        = sum(WASH),
                       salud_ben       = sum(Salud),
                       educacion_ben   = sum(Educacion),
                       sa_ben          = sum(Seguridad_Alimentaria), .groups = "drop") %>% 
             mutate(ben_freq   = nutricion_ben + proteccion_ben + wash_ben + salud_ben +
                                 educacion_ben + sa_ben,
                    ben_max    = pmax(nutricion_ben, proteccion_ben, wash_ben, 
                                      salud_ben, educacion_ben, sa_ben),
                    ms_ben_max = ifelse(ben_max >= ben_freq - ben_max, 
                                        ben_freq - ben_max, 
                                        ben_max)) %>% 
             group_by(pcode3) %>% 
             summarise(nutricion_ben  = sum(nutricion_ben),
                       proteccion_ben = sum(proteccion_ben),
                       wash_ben       = sum(wash_ben),
                       salud_ben      = sum(salud_ben),
                       educacion_ben  = sum(educacion_ben),
                       sa_ben         = sum(sa_ben),
                       ben_freq   = sum(ben_freq),
                       ben_max    = sum(ben_max),
                       ms_ben_max = sum(ms_ben_max), .groups = "drop") %>% 
             mutate(sector_count = rowSums(select(., ends_with("_ben")) != 0)) %>% 
  group_by(sector_count) %>% 
  # filtering out the parrishes with oversubscription 
  filter(pcode3 %out% c("VE010101", "VE070104", "VE070502", "VE070506", "VE081401", "VE100401",
                        "VE150701", "VE151901", "VE151905", "VE200101", "VE200403")) %>% 
  summarise(parroquias = n(),
            multi_sector_ben = sum(ms_ben_max),
            one_sector_ben = sum(ben_freq) - sum(ms_ben_max), 
            `multisector_%` = round(sum(ms_ben_max) / sum(ben_freq) * 100, digits = 2),
            .groups = "drop") %>% 
  relocate(`multisector_%`, .after = one_sector_ben) %>% 
  pander(style = "rmarkdown", caption = "Summary of multisector coverage")
Summary of multisector coverage
sector_count parroquias multi_sector_ben one_sector_ben multisector_%
1 352 0 225,335 0
2 102 31,272 153,617 16.91
3 60 36,498 136,449 21.1
4 39 108,052 280,180 27.83
5 18 69,634 158,997 30.46
6 5 23,211 36,649 38.78

Overall, the results are not encouraging – only 21.9% of all beneficiaries have received multi-sector support. When vaccinations are included, the percentage drops to 8.7%. But we will exclude vaccinations for this analysis as their footprint is determined by government priorities, which do not align with the humanitarian imperative; furthermore, the government was not able to provide vaccination records at the parrish level, many times defaulting to municipal or state-level reporting.

As the leader of the Education, Nutrition, WASH and Child Protection Clusters, UNICEF supported activities reaching 95% of all beneficiaries. Meaning that this the low percentage of multi-sector support could be resolved almost entirely by better inter-section coordination and better programmatic oversight within UNICEF – this will be even more apparent in sections 4c and 4d.


4b. Parrish-level gaps in multi-sector programming

A total of 537,185 beneficiaries received support from only one sector – this is 78.1% of all beneficiary frequencies. Parrishes below have been plotted according to their multi-sector coverage and their total number of beneficiary frequencies; larger sizes indicate parrishes where there are higher numbers of beneficiaries benefitting from only one sector:

ms_scatter <- parr0 %>% 
  mutate(multi_sector_percent = round(ms_ben_max / ben_freq * 100, digits = 1),
         one_sector_percent = round((ben_freq - ms_ben_max) / ben_freq * 100, digits = 1),
         multi_sector_ben = round(ms_ben_max, digits = 0),
         one_sector_ben = round(ben_freq - ms_ben_max, digits = 0),
         ben_freq = round(ben_freq, digits = 0)) %>% 
  ggplot(aes(x = ben_freq, 
             y = multi_sector_percent, 
             text = paste0(parroquia,",", "\n", 
                           municipio, ",", "\n",
                           estado, ",", "\n",
                           "sector count: ", sector_count),
             colour = estado)) +
  geom_point(aes(size = one_sector_ben), 
             alpha = 0.8) +
  scale_x_continuous(trans = "log10", labels = label_comma(accuracy = 1)) +
  scale_size_continuous(range = c(0.1, 5)) +
  scale_colour_manual(values = c(rep("coral",24))) +
  xlab("Beneficiary frequencies") + ylab("Percentage received multi-sector support") +
  labs(title = "Scatterplot of parrishes by beneficiary frequencies and multi-sector coverage", 
       size = "", colour = "") +
  theme(plot.title = element_text(size = 11),
        axis.title = element_text(size = 8.5))

ggplotly(ms_scatter, tooltip = c("x", "y", "size", "text")) %>% 
  layout(legend = list(font = list(size = 6))) %>% 
  config(displayModeBar = FALSE) %>% 
  layout(title = list(text = paste0(
    "Scatterplot of parrishes by beneficiary frequencies and multi-sector coverage",
                                    "<br>",
                                    "<sup>",
                                    "size: number of beneficiaries supported by only one sector; double-click state to toggle view; mouse over for details","</sup>")))

We note only a very loose relationship (r-squared = 0.203) between the number of beneficiary frequencies and the percentage of those beneficiary frequencies reached by interventions from multiple sectors. There is little else it is correlated with and, as can be seen below, there is no discernible pattern to multisector coverage.

However, we do note that in the states where UNICEF has offices (Bolivar, Tachira, Zulia and Distrito Capital), there is much higher multi-sector coverage than in other states, perhaps indicating that a more decentralised approach where field offices have greater say in prioritisation might lead to more coordination in multi-sector programming. Though, that this greater multi-sector coverage has not expanded outside of these areas is indicative of the level of planning and coordination capacity field offices are capable of.

There are the 351 parrishes at the bottom of the plot; there is only one sector present in each – this is 61.8% of all parrishes we are responding in.

parr0 %>% 
  filter(beneficiarios != 0) %>% 
  select(estado, sector_count) %>% 
  group_by(estado) %>% 
  summarise(avg_sector = round(mean(sector_count), digits = 2)) %>% 
  arrange(desc(avg_sector)) %>% 
  filter(avg_sector > 2 | avg_sector < 1.19) %>% 
  pivot_wider(names_from = estado, values_from = avg_sector) %>% 
  mutate(`||` = c("")) %>% relocate(`||`, .after = BOLIVAR) %>% 
  pander(caption = "Top 5 and bottom 5 states, average number of sectors per parrish", missing = "")
Top 5 and bottom 5 states, average number of sectors per parrish
DISTRITO CAPITAL TACHIRA MIRANDA ZULIA BOLIVAR || ARAGUA BARINAS CARABOBO NUEVA ESPARTA TRUJILLO
3.38 2.61 2.41 2.38 2.37 1.15 1.14 1.08 1.05 1.02


4c. Cluster combinations

This section will examine the parrishes that have multi-sector coverage and the types of inter-cluster combinations that can be found in them. Let us begin with an overview of the geographic reach of each cluster – we use frequencies here, as each individual might have benefitted from multiple combinations of clusters:

act_ben %>% 
  filter(sector != "Seguridad_Alimentaria" & categoria != "VACUNACION") %>% 
  mutate(sector = ifelse(str_detect(sector, "Proteccion_GBV|Proteccion_General|Proteccion_NNA"), 
                         "Proteccion", sector)) %>% 
  # mutate(sector = ifelse(categoria == "VACUNACION", "Vacunacion", sector))
  # we're not going to look at vaccination in this report 
  group_by(sector) %>% 
  summarise(parrishes = n_distinct(pcode3),
            beneficiary_frequencies = sum(beneficiarios)) %>% 
  rename(cluster = sector) %>% 
  pander(caption = "Cluster summary, vaccination exluded", big.mark = ",", style = "rmarkdown", 
         justify = c("left", "right", "right"))
Cluster summary, vaccination exluded
cluster parrishes beneficiary_frequencies
Educacion 186 624,908
Nutricion 497 352,248
Proteccion 151 183,014
Salud 62 54,800
WASH 126 809,202

Next, we will summarise the inter-cluster combinations according to:

  • combination, referring to the various cluster-wise pairs that exist;
  • parrishes, indicating the number of parrishes each combination is present in;
  • cluster1 and cluster2, which show the number of beneficiary frequencies reached by both clusters in each pair, in the order that they appear in combination.
  • pair_sum, which shows the total number of beneficiary frequencies in that pair i.e. the pair_sum for edu_nut would be the sum of education and nutrition beneficiaries.
  • %ms_max, which shows the maximum percentage of multisector beneficiaries of each pair i.e. if the pair edu-nut has 10 education beneficiaries and 30 nutrition beneficiaries, the maximum number of beneficiaries which received support from both sectors is 10, resulting in a %_ms_max of 25%. But, as mentioned in the notes for section 4a, this is a theoretical maximum and the actual level of coincidence is likely much lower.
# creation of reference df for the cluster combinations 
clust_com <- parr %>% 
  filter(ben_freq != 0) %>% 
  select(pcode3, ben_freq, educacion_ben, nutricion_ben, salud_ben, wash_ben, proteccion_ben) %>%
  # mutate a new column for each combination of sectors -- if edu is the first cluster in the combination, 
  # only education beneficiaries will be used to fill values in the column 
  mutate(edu_only = ifelse(educacion_ben == ben_freq, educacion_ben, 0),
         edu_nut = ifelse(educacion_ben > 0 & nutricion_ben > 0, educacion_ben + nutricion_ben, 0),
         edu_sal = ifelse(educacion_ben > 0 & salud_ben > 0, educacion_ben + salud_ben, 0),
         edu_wash = ifelse(educacion_ben > 0 & wash_ben > 0, educacion_ben + wash_ben, 0),
         edu_prot = ifelse(educacion_ben > 0 & proteccion_ben > 0, educacion_ben + proteccion_ben, 0),
         nut_only = ifelse(nutricion_ben == ben_freq, nutricion_ben, 0),
         nut_sal = ifelse(nutricion_ben > 0 & salud_ben > 0, nutricion_ben + salud_ben, 0), 
         nut_wash = ifelse(nutricion_ben > 0 & wash_ben > 0, nutricion_ben + wash_ben, 0), 
         nut_prot = ifelse(nutricion_ben > 0 & proteccion_ben > 0, nutricion_ben + proteccion_ben, 0),
         sal_only = ifelse(salud_ben == ben_freq, salud_ben, 0),
         sal_wash = ifelse(salud_ben > 0 & wash_ben > 0, salud_ben + wash_ben, 0),
         sal_prot = ifelse(proteccion_ben > 0 & salud_ben > 0, salud_ben + proteccion_ben, 0),
         wash_only = ifelse(wash_ben == ben_freq, wash_ben, 0),
         prot_wash = ifelse(wash_ben > 0 & proteccion_ben > 0, wash_ben + proteccion_ben, 0),
         prot_only = ifelse(proteccion_ben == ben_freq, proteccion_ben, 0)) %>% 
  # pivot_longer to the clust_freq column 
  pivot_longer(names_to = "combination", values_to = "pair_sum", 8:22) %>%
  filter(pair_sum != 0) %>% 
  group_by(pcode3, combination) %>% 
  summarise(educacion_ben = mean(educacion_ben),
            nutricion_ben = mean(nutricion_ben),
            salud_ben = mean(salud_ben),
            wash_ben = mean(wash_ben),
            proteccion_ben = mean(proteccion_ben),
            pair_sum = sum(pair_sum)) %>% 
  # calculating the sum of frequencies in each pair
  mutate(cluster1 = 
           case_when(
             str_detect(combination, "edu_nut") ~ educacion_ben,
             str_detect(combination, "edu_sal") ~ educacion_ben,
             str_detect(combination, "edu_wash") ~ educacion_ben,
             str_detect(combination, "edu_prot") ~ educacion_ben,
             str_detect(combination, "nut_sal") ~ nutricion_ben,
             str_detect(combination, "nut_wash") ~ nutricion_ben,
             str_detect(combination, "nut_prot") ~ nutricion_ben,
             str_detect(combination, "sal_wash") ~ salud_ben,
             str_detect(combination, "sal_prot") ~ salud_ben,
             str_detect(combination, "prot_wash") ~ proteccion_ben,
             str_detect(combination, "edu_only") ~ educacion_ben,
             str_detect(combination, "nut_only") ~ nutricion_ben,
             str_detect(combination, "sal_only") ~ salud_ben,
             str_detect(combination, "wash_only") ~ wash_ben,
             str_detect(combination, "prot_only") ~ proteccion_ben)) %>%
  mutate(cluster2 = 
           case_when(
             str_detect(combination, "edu_nut") ~  nutricion_ben,
             str_detect(combination, "edu_sal") ~  salud_ben,
             str_detect(combination, "edu_wash") ~ wash_ben,
             str_detect(combination, "edu_prot") ~ proteccion_ben,
             str_detect(combination, "nut_sal") ~  salud_ben,
             str_detect(combination, "nut_wash") ~ wash_ben,
             str_detect(combination, "nut_prot") ~ proteccion_ben,
             str_detect(combination, "sal_wash") ~ wash_ben,
             str_detect(combination, "sal_prot") ~ proteccion_ben,
             str_detect(combination, "prot_wash") ~ wash_ben,
             str_detect(combination, "only$") ~ 0)) %>%
  select(pcode3, combination, cluster1, cluster2, pair_sum)

# pander table cluster combinations 
rbind(
clust_com %>%  
  filter(str_detect(combination, "only$")) %>% 
  group_by(combination) %>% 
  summarise(parrishes = n(),
            cluster1 = sum(cluster1),
            cluster2 = sum(cluster2),
            pair_sum = sum(pair_sum)) %>% 
  mutate(`%ms_max` = pmin(cluster1, cluster2) / pair_sum * 100,
         `%ms_max` = round(ifelse(is.nan(`%ms_max`), 0, `%ms_max`), digits = 1)) %>% 
  arrange(desc(pair_sum)) %>% 
  rbind(NA),

clust_com %>%  
  filter(!str_detect(combination, "only$")) %>% 
  group_by(combination) %>% 
  summarise(parrishes = n(),
            cluster1 = sum(cluster1),
            cluster2 = sum(cluster2),
            pair_sum = sum(pair_sum)) %>% 
  mutate(`%ms_max` = pmin(cluster1, cluster2) / pair_sum * 100,
         `%ms_max` = round(ifelse(is.nan(`%ms_max`), 0, `%ms_max`), digits = 1)) %>% 
  arrange(desc(pair_sum))

) %>% 

  pander(caption = "Cluster combinations, sorted by pair_sum", big.mark = ",", missing = "",  
         justify = c("left", "right", "right", "right", "right", "right"))
Cluster combinations, sorted by pair_sum
combination parrishes cluster1 cluster2 pair_sum %ms_max
nut_only 282 48,576 0 48,576 0
edu_only 33 26,570 0 26,570 0
wash_only 12 5,663 0 5,663 0
prot_only 15 2,796 0 2,796 0
sal_only 3 142 0 142 0
edu_wash 83 204,964 706,930 911,894 22.5
prot_wash 67 108,595 689,628 798,223 13.6
nut_wash 97 53,753 705,108 758,861 7.1
sal_wash 32 32,372 299,276 331,648 9.8
edu_nut 132 241,390 65,034 306,424 21.2
edu_prot 81 183,820 111,714 295,534 37.8
nut_prot 125 57,871 144,942 202,813 28.5
edu_sal 38 82,489 34,241 116,730 29.3
sal_prot 34 34,339 50,529 84,868 40.5
nut_sal 48 25,875 36,842 62,717 41.3


The most common pairing was between the Nutrition and Education clusters – they coincide in 132 parrishes, followed by Nutrition and Protection. In the next section, we will investigate whether the substantial overlap between Nutrition and Protection at the parrish level was coordinated or – as in the case with its overlap with Education, where there are no concrete programmatic links – due more to its wide operational presence.

Protection and WASH, however, both do have explicit programmatic links (in the logframe) with Education and 81 and 83 parrishes respectively. A fruitful avenue of investigation would be how many beneficiaries of Education also benefitted from Protection interventions and how close it is to the 37.8% theoretical maximum.

Nutrition operates alone in 282 parrishes out of the 497 that it is present in, this is the most out of any of the other clusters – it is necessary to evaluate the extent to which other clusters can make use of the footholds established by Nutrition.

Whilst Nutrition and Health have excellent programmatic complementarity, especially with Health’s focus on obstetric, antenatal and neonatal care, this combination has the lowest number of beneficiary frequencies of all the combinations.

Almost none of WASH’s beneficiary frequencies occurred in parrishes where no other clusters were present. Its great reach and blanket coverage (especially water supply and other community-level activities) mean that other clusters operating in the same areas as WASH are “guaranteed” to reach beneficiaries with multi-sector programming – the challenges of these combinations being 1. the intentionality of the multi-sector coverage and 2. matching the scale of WASH activities. WASH has excellent programmatic overlap with all other clusters. WASH is the only sector to programme specific multi-sector interventions – WASH in schools and WASH in health/nutrition centres.

Like WASH and Health, Protection has very limited beneficiary frequencies in parrishes where it operates alone. Protection coincides the most with Nutrition – this should serve as an impulse for the creation of referral pathways between the two since both carry out screening activities, made easier by the fact that both manage some form of beneficiary-level database. Protection has the most explicit progammatic links to Education in the logframe.


4d. Activity categories

To close, the state of multi-sector programming is poor. There is little intentionality in which areas have multi-sector coverage and which areas do not – multi-sector links do exist at the activity level, but this is a poor approximation of developing a programme based on the specific needs of a target area. And we see the weakness of this approach in the table below which lists the most common inter-cluster activity category combinations at the parrish level.

cat <- act_ben %>% 
  filter(categoria != "VACUNACION" & categoria != "OTRO") %>% 
  group_by(pcode3, categoria) %>% 
  summarise(beneficiarios = sum(beneficiarios)) %>% 
  pivot_wider(names_from = categoria, values_from = beneficiarios) %>%
  replace(is.na(.), 0) %>% 
  group_by(pcode3) %>% 
  summarise(across(everything(), ~ sum(., is.na(.), 0)), .groups = "drop") %>% 
  mutate(PREVENCION_DESNUTRICION_AGUDA = ifelse(PREVENCION_DESNUTRICION_AGUDA != 0,
                                                "PREVENCION_DESNUTRICION_AGUDA", NA_character_),
         CAPACITACIONES_PROTECCION = ifelse(CAPACITACIONES_PROTECCION != 0,
                                            "CAPACITACIONES_PROTECCION",NA_character_),
         TRATAMIENTO_DESNUTRICION_AGUDA = ifelse(TRATAMIENTO_DESNUTRICION_AGUDA != 0,
                                                 "TRATAMIENTO_DESNUTRICION_AGUDA", NA_character_),
         ASISTENCIA_ALIMENTARIA = ifelse(ASISTENCIA_ALIMENTARIA != 0, 
                                         "ASISTENCIA_ALIMENTARIA", NA_character_),
         RESILENCIA_EDUCACION = ifelse(RESILENCIA_EDUCACION != 0, "RESILENCIA_EDUCACION", NA_character_),
         FORTALECIMIENTO_INSTITUCIONAL = ifelse(FORTALECIMIENTO_INSTITUCIONAL != 0,
                                               "FORTALECIMIENTO_INSTITUCIONAL", NA_character_),
         WASH_EN_EDUCACION = ifelse(WASH_EN_EDUCACION != 0, 
                                    "WASH_EN_EDUCACION", NA_character_), 
         SEGURIDAD_ALIM_INSTITUCIONAL = ifelse(SEGURIDAD_ALIM_INSTITUCIONAL != 0,
                                               "SEGURIDAD_ALIM_INSTITUCIONAL", NA_character_),
         VIH = ifelse(VIH != 0, "VIH", NA_character_),
         SALUD_POBLACIONAL = ifelse(SALUD_POBLACIONAL != 0, 
                                    "SALUD_POBLACIONAL", NA_character_),
         PROVISION_DE_SERVICIO = ifelse(PROVISION_DE_SERVICIO != 0,
                                              "PROVISION_DE_SERVICIO", NA_character_),
         INCIDENCIA_CON_AUTORIDADES = ifelse(INCIDENCIA_CON_AUTORIDADES != 0,
                                                "INCIDENCIA_CON_AUTORIDADES", NA_character_),
         COMUNIDADES_SALUD = ifelse(COMUNIDADES_SALUD != 0, 
                                    "COMUNIDADES_SALUD", NA_character_),
         RED_INTEGRADA_SALUD = ifelse(RED_INTEGRADA_SALUD != 0, 
                                      "RED_INTEGRADA_SALUD", NA_character_),
         INFORMACION_RIESGOS = ifelse(INFORMACION_RIESGOS != 0, 
                                      "INFORMACION_RIESGOS", NA_character_),
         PROVISION_DE_SERVICIOS = ifelse(PROVISION_DE_SERVICIOS != 0,
                                            "PROVISION_DE_SERVICIOS", NA_character_),
         PROMOCION_HIGIENE = ifelse(PROMOCION_HIGIENE != 0, 
                                    "PROMOCION_HIGIENE", NA_character_),
         AGUA_EN_COMUNIDADES = ifelse(AGUA_EN_COMUNIDADES != 0, "AGUA_EN_COMUNIDADES", NA_character_),
         WASH_EN_SALUD_NUTRICION = ifelse(WASH_EN_SALUD_NUTRICION != 0, 
                                          "WASH_EN_SALUD_NUTRICION", NA_character_),
         FORTALECIMIENTO_CAPACIDAD_EDUCACION = ifelse(FORTALECIMIENTO_CAPACIDAD_EDUCACION != 0,
                                                      "FORTALECIMIENTO_CAPACIDAD_EDUCACION", NA_character_),
         ACCESO_PERMANENCIA_ESCOLAR = ifelse(ACCESO_PERMANENCIA_ESCOLAR != 0, 
                                             "ACCESO_PERMANENCIA_ESCOLAR", NA_character_),
         SALUD_MATERNA_INFANTIL = ifelse(SALUD_MATERNA_INFANTIL != 0, 
                                         "SALUD_MATERNA_INFANTIL", NA_character_),
         SUMINISTROS_MEDICAMENTOS_BASICOS = ifelse(SUMINISTROS_MEDICAMENTOS_BASICOS != 0, 
                                                   "SUMINISTROS_MEDICAMENTOS_BASICOS", NA_character_),
         SANEAMIENTO = ifelse(SANEAMIENTO != 0, 
                              "SANEAMIENTO", NA_character_),
         RED_DE_PROTECCION = ifelse(RED_DE_PROTECCION != 0, "RED_DE_PROTECCION", NA_character_),
         CAPACITACIONES_NUTRICION = ifelse(CAPACITACIONES_NUTRICION != 0, 
                                           "CAPACITACIONES_NUTRICION", NA_character_),
         ESTABLECIMIENTOS_SALUD = ifelse(ESTABLECIMIENTOS_SALUD != 0, 
                                         "ESTABLECIMIENTOS_SALUD", NA_character_))  

cat_comb<- t(combn(sort(na.omit(unique(unlist(cat[,-1])))), 2))

cat_freqs <- apply(cat_comb, 1, function(C) {
  sum(apply(cat[,-1], 1, function(a) all(C %in% a, na.rm = TRUE)))
})

as.data.frame(cat_comb) %>% 
  mutate(count = cat_freqs) %>% 
  left_join(act_ben %>% select(cluster1 = sector, V1 = categoria) %>% distinct(), by = "V1") %>% 
  left_join(act_ben %>% select(cluster2 = sector, V2 = categoria) %>% distinct(), by = "V2") %>% 
  mutate(multicluster = ifelse(cluster1 != cluster2, 1, 0),
         combination = paste0(V1," / ", V2)) %>%
  filter(multicluster == 1) %>% 
  select(combination, count) %>%
  mutate(combination =str_to_title(combination)) %>% 
  distinct() %>% 
  arrange(desc(count)) %>% 
  head(15) %>% 
  pander(caption = "Most common inter-cluster activity category combinations", style = "rmarkdown",  
         justify = c("left", "right"))
Most common inter-cluster activity category combinations
combination count
Acceso_permanencia_escolar / Prevencion_desnutricion_aguda 114
Prevencion_desnutricion_aguda / Resilencia_educacion 107
Fortalecimiento_capacidad_educacion / Prevencion_desnutricion_aguda 101
Prevencion_desnutricion_aguda / Provision_de_servicios 91
Acceso_permanencia_escolar / Tratamiento_desnutricion_aguda 78
Resilencia_educacion / Tratamiento_desnutricion_aguda 73
Fortalecimiento_capacidad_educacion / Tratamiento_desnutricion_aguda 72
Capacitaciones_proteccion / Prevencion_desnutricion_aguda 69
Fortalecimiento_institucional / Prevencion_desnutricion_aguda 56
Agua_en_comunidades / Prevencion_desnutricion_aguda 53
Provision_de_servicios / Tratamiento_desnutricion_aguda 52
Acceso_permanencia_escolar / Provision_de_servicios 51
Prevencion_desnutricion_aguda / Wash_en_salud_nutricion 50
Provision_de_servicios / Resilencia_educacion 49
Fortalecimiento_capacidad_educacion / Provision_de_servicios 47

Of the 15 most common activity category combinations, we see four combinations which actually convey multi-sector benefits:

  • The 4th and 11th entries, Prevention of acute malnutrition / Provision of protection services and Provision of protection services / Treatment of acute malnutrition where referrals between the Nutrition and Protection clusters might feasibly result in vulnerable populations receiving a combination of protection services, micronutrient supplementation, de-worming, treatment and counselling that would reduce their vulnerability in a multidimensional manner; the
  • 9th entry, Water supply in communities / Prevention of acute malnutrition, as improved water supply is a core component of preventing malnutrition; and the
  • 11th, Access to education and student retention / Provision of protection services, as the population of children with poor access to education and are in danger of dropping out would, presumably, be more in need of protection services (which include referrals to the formal social welfare system, legal aid, support for GBV survivors and UASC).

However, as mentioned previously, these multi-sector benefits are theoretical and it has not been established that there is communication between the implementing partners of these activities. Project monitoring is required to establish this.

Combinations like Access to education and student retention / Prevention of acute malnutrition(1st) deal with almost entirely separate populations – children of schoolgoing age are outside of the target population for Nutrition; though it is feasible that Education and Nutrition might both be dealing with the same young mother who has dropped out of school.

Furthermore, combinations like Prevention of acute malnutrition / Resilience in education(2nd) and Capacity building in education / Prevention of acute malnutrition(3rd) have no overlap as malnutrition prevention has no programmatic link to safe school strategies, DRR in schools and teacher training.

As it stands, cluster footprints seem to have much more to do with opportunistic expansion strategies dependent on implementing partner capacities and where they have negotiated access with local governments than a needs-based approach which targets the most vulnerable. The next part is an effort to examine and correct this.


5. Decision trees

5a. Introduction to trees – orgasational presence

To prioritise between the 1109 parrishes in Venezuela – that is, to determine where we should be working – it is necessary to split them up into more easily digestible groups, and we will use decision trees to do this. A prioritisation or vulnerability score is another commonly-used prioritisation tool, but, as we will see, collapsing a number of variables down into one score is not always helpful.

To understand how a decision tree functions, let us construct one to predict whether or not there is a humanitarian agency present in a parrish (org_present – this is our dependent variable). We have supplied our model with a basket of census indicators from which it will construct a tree to predict our – unhide the code below to see the full model. The decision tree printed below is the result:

# just to show the decision tree of how partners seem to have chosen locations. 
# using full parr dataset for the tree
# no doubt there are other factors, but this is the data I have -- 
# looking at specific partner characteristics would be interesting. 
set.seed(3000)

tree2 <- parr %>% 
  rpart(org_present ~ percent_pobre + percent_urbana + densidad_ppl_km2 + 
        razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
        promedio_de_personas_por_vivienda, data = ., minbucket = 100)

fancyRpartPlot(tree2, digits = -3, sub = "", palettes = "Blues", type = 2)

To understand the plot above, all parrishes have been split into four groups (the terminal nodes at the bottom marked [4], [5], [6] and [7]) based on the percentage of parrishes in each node where humanitarian agencies are present. Each node has three figures – for instance, the root, at the top, and marked [1], shows that on average, 0.524 or 52.4% of all parrishes have humanitarian agencies present in them. The next numbers, “n = 1109” shows that 1109 parrishes are in that group and next to it is the percentage of parrishes it contains, which, since it is the root, is 100%.

We see that [7] (in dark blue) the node with the highest concentration of parrishes with agencies present (82.8%), consists of parrishes more than 79.4% urbanised and denser than 187 ppl/km2. And [4], the node with the lowest concentration of parrishes with agencies (22.6%) is less than 79.4% urbanised and less than 21.8% urbanised.

This is, of course, not to imply that this actually depicts partners’ decision-making process, just that these are the factors towards which we, as a response, are predisposed. Perhaps it is understandable that the most heavily populated parrishes are more likely to have organisations present, though population density and urban population are both negatively correlated with poverty incidence. The largest determinants of the number of beneficiaries reached per parrish are population density and urbanisation, as beneficiary numbers tend to scale in line with larger populations.


5b. Prioritisation trees

Now let us start on where to go from here:

Several trees were built and trialled to split parrishes into targetting groups. As mentioned, the independent variables come from a pool of indicators from the census dataset, with some originating from the 2019 UNICEF Municipal Prioritisation Tool, which was a Principal Components Analysis of key variables related to poverty, health and mortality and violence and insecurity. After numerous iterations, tree3 was chosen and it splits parrishes into groups according to the:

  • The poverty score, which is the a rescaled average of the number of poor persons and the poverty incidence of each parrish.

To see the specific variables and formulae used for each of the major iterations, as well as additional notes on the development and application of decision trees, unhide the source code below.

# As opposed to a prioritisation score -- typically the weighted average of several demographic and socioeconomic indicators -- a tree is much better at accounting for the variations across geographic areas. A partner might not have the capacity to work outside of urban areas or another might have specific geographic biases and decision trees are a good tool to make the best possible targetting decisions within one's constraints.  

# With that in mind, tree3 was developed to aid future prioritisation. The independent variable it strives to predict is the poverty score, which, as mentioned, is just the rescaled average of number of poor persons and poverty incidence. The performance of tree3 was considered superior to both tree1 (whose indendepent variable is just the absolute number of poor persons) and tree4 (which considered parrish-level gaps) due to its ability clearly distinguish its groups of parrishes and because it is not dependent on gaps data -- meaning it will not shift when the 5Ws are updated.

set.seed(3000)

# number of not covered poor persons 
tree1 <- parr0 %>%
  rpart(not_reached ~ estado + percent_pobre + percent_urbana + 
        densidad_ppl_km2 + razon_de_dependencia_de_menores_de_15_anos + 
        razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
        promedio_de_personas_por_vivienda, data = ., cp = 0.038)

# tree based on poverty_score
tree3 <- parr0 %>%
  rpart(poverty_score ~ estado + percent_urbana + densidad_ppl_km2 +
        razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
        percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
        percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
        promedio_de_personas_por_vivienda, data = ., cp = 0.044)

# tree based on gap score -- let's not use this as tree3 is more stable and will not change based on new 5W data 
# tree4 <- parr0 %>%
#   rpart(gap_score ~ estado + percent_urbana + densidad_ppl_km2 +
#         razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +  
#         percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
#         percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina, 
#         promedio_de_personas_por_vivienda, data = ., cp = 0.045)

# plotcp(tree3)
# printcp(tree3)

# adding tree1 and tree3 rules to the dataset 
parr0 <- parr0 %>% 
  mutate(rule1 = row.names(tree1$frame)[tree1$where]) %>%
      left_join(rpart.rules.table(tree1) %>% 
      filter(Leaf == TRUE) %>% 
      rename(rule1 = Rule) %>% 
      group_by(rule1) %>% 
      summarise(subrules1 = paste(Subrule, collapse = ",")))  %>% 
  mutate(rule3 = row.names(tree3$frame)[tree3$where]) %>%
      left_join(rpart.rules.table(tree3) %>% 
      filter(Leaf == TRUE) %>% 
      rename(rule3 = Rule) %>% 
      group_by(rule3) %>% 
      summarise(subrules3 = paste(Subrule, collapse = ",")))


5c. Sub-groups of decision tree3

Below is a plot of tree3 – the 1098 parrishes where the number of beneficiaries does not exceed the number of poor persons (corresponding to the under and no coverage categories) have been split into four terminal nodes: [4], [5], [6] and [7]. The manner in which they have been split is meaningful for targetting decisions and this section will compare the characteristics of each. Please note that this is a different tree than in section 5a – the terminal nodes have the same numbering just because the two models have the same number of rules.

fancyRpartPlot(tree3, digits = -3, sub = "", palettes = "Blues", type = 2)


Summary and overview of the terminal nodes of tree3

# will they be confused that the terminal nodes have the same codes? Should I explain in the text that this is because they have the same number of rules or will that just make them more confused? 

parr0 %>% 
  group_by(rule3) %>% 
  summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]),
            beneficiarios = sum(beneficiarios),
            avg_beneficiarios = sum(beneficiarios) / n(), 
            not_reached = sum(not_reached),
            avg_not_reached = sum(not_reached) / n(),
            avg_org_count = mean(org_count),
            avg_poblacion = mean(poblacion_2019),
            percent_pobre = round(sum(pob_pobre) / sum(poblacion_2019), digits = 2),
            percent_urbana = round(sum(pob_urbana) / sum(poblacion_2019), digits = 2),
            densidad_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
            parroquias = n()) %>% 
  gather(key = variable, value = value, 2:ncol(.)) %>% 
  spread_(key = names(.)[1], value = 'value') %>% 
  # reordering the table instead of having it be alphabetical
  arrange(factor(variable, levels = c("not_reached", "avg_not_reached", "avg_poblacion", 
                                      "beneficiarios",
                                      "avg_beneficiarios",  "avg_org_count",
                                      "percent_pobre", "percent_urbana", "densidad_ppl_km2", 
                                      "parroquias", "parr_no_ben"))) %>%  
  
  pander(big.mark = ",")
variable 4 5 6 7
not_reached 1,091,079 6,371,849 3,648,710 522,263
avg_not_reached 8,659 12,898 9,653 5,223
avg_poblacion 46,126 35,806 19,120 7,174
beneficiarios 176,330 352,663 111,813 17,452
avg_beneficiarios 1,399 713.9 295.8 174.5
avg_org_count 2.508 1.666 0.9683 0.39
percent_pobre 0.22 0.38 0.52 0.75
percent_urbana 0.99 0.93 0.75 0.23
densidad_ppl_km2 996.1 147.4 18.07 1.855
parroquias 126 494 378 100
parr_no_ben 38 211 205 76
  • [4] consists of population centres which are easy to reach, but with only 21.8% of the population being poor, careful targetting and beneficiary selection is required – blanket coverage will only result in excessive inclusion errors. It also has the highest average number of organisations present per parrish (avg_org_count). There are 126 parrishes in this group. These parrishes should not be prioritised – resources should be allocated elsewhere.

  • [5] is probably the best option for expansion for most partners – it has the highest concentration of poor persons not covered per parrish (nc_per_parr), is substantially poorer than [4], with a poverty incidence of 38%. Additionally, these parrishes are still very urbanised (92.5%), meaning that access to these populations will not be challenging. The coverage of organisations is still fairly high and partners should consider expanding into parrishes to the ones they currently cover. This is the largest group, with 494 parrishes.

  • [6] is where access starts to get more challenging – though these parrishes have an average poverty incidence of 52%, the rate of urbanisation drops to 75% and the population density is only 18 ppl/km2. But there are still more poor persons not covered per parrish in this group than in [4]. There are 378 parrishes in this group.

  • [7] consists of the poorest, most vulnerable and most remote parrishes. Working in these areas will incur significant operational and logistical costs. However, with an average poverty incidence of 75.2%, blanket coverage will be warranted in many cases – if the challenge of reaching all of the population can be met. Additionally, they also have the lowest average number of poor persons not covered, given their extremely low population density of 1.8 ppl/km2. Humanitarian agencies have the lowest presence in these parrishes. It is advisable for donors to incentivise activities in these areas as it is clear that humanitarian agencies are avoiding them. There are 100 parrishes in this group.


5d. Maps of parrishes by decision tree node

# just one note for this map -- I still can't figure out how to get the tooltip to appear when
# you're hovering over the centroid instead of at the border; hoveron fill doesn't work. 
# I think you should just ask stackoverflow GIS

# hex for Set2 "#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3", "#FFFFFF"
# hex for Dark2 "#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#FFFFFF"
# hex for Accent "#7FC97F", "#BEAED4", "#FDC086", "#FFFF99", "#FFFFFF"
# scale_fill_viridis_d()
# scale_fill_manual(values = c())

parrmap_org <- parr %>% 
  left_join(parr0 %>% 
              select(pcode3, rule3), by = "pcode3") %>% 
  right_join(pcode3_shape, by = "pcode3") %>% 
  st_as_sf() %>% 
  mutate(not_reached = round(not_reached, digits = 0),
         tree_node = rule3) %>% 
  mutate_at(vars(percent_pobre, percent_urbana), ~(round(., digits = 2))) %>% 
  ggplot() +
  geom_sf(size = 0.1, 
          aes(fill = tree_node,
              text = paste0(parroquia,",", "\n", 
                           municipio, ",", "\n",
                           estado, "\n", 
                           "not covered: ", not_reached, "\n",
                           "poverty incidence: ", percent_pobre, "\n",
                           "percent urban: ", percent_urbana, "\n",
                           "org present :", org_present),
             alpha = org_present)) +
  theme_void() +
  scale_fill_manual(values = c("#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3")) +
  scale_alpha_discrete(range = c(1, 0.7)) +
  theme(legend.title = element_text(size = 7),
        legend.text = element_text(size = 7),
        plot.title = element_text(size = 11)) +
  guides(alpha = FALSE) +
  labs(fill = "Tree node",
       alpha = "") +
  ggtitle('Map of parrishes by decision tree node (colour) & if organisations present (alpha)')
  
ggplotly(parrmap_org, tooltip = c("text", "fill")) %>%
  layout(title = list(text = paste0(
    "Map of parrishes by decision tree node (colour) & if organisations present (alpha)",
                                    "<br>",
                                    "<sup>",
                                     "mouse over for details; drag and click to select and zoom; double-click legend select/deselect","</sup>")))

Above is a map of parrishes by their decision tree node (denoted by colour), we have also decreased the alpha for parrishes where there are already organisations present, meaning that they appear more transparent. Looking at [4] and [5], we can see the parrishes that conform to the the Venezuela Costal Range and the Venezuelan Andes, where most of the country’s population is concentrated; as a reminder, parrishes in node [5] are excellent candidates for expansion.

We also see three large clusters of parrishes from node [7] – the poorest and most-sparsely populated areas – in Amazonas and Bolivar (at the bottom of the map), in Delta Amacuro (at the extreme right) and in Lara and Falcon (top-left). Double-click on each legend item to toggle the view.


  • Part 5 annex: Additional notes on tree1, which was not selected – unhide code to see
# the main problem I see is that each of the leaves has little variance in terms of poverty incidence
# but let me know if you want maps or products focused on this tree, it's pretty easy to do. [15] is very, very attractive. Maybe I can do something with it.  

# 6 is dense, urban and highest operational presence,
# 2 is just too big. 800 parrishes is just too many. The low end is distinguished much better in tree3
# 14 is just rich, urban and not a priority. It's also a really small leaf.  
# 15 is actually a really good leaf -- really high nc_per_parr, few parrishes, very dense, very urban and 42% poor and such an immensely low coverage percent. Good low-hanging fruit. I almost want to keep tree1 just because of this leaf. Maybe I will make one map just for this. 59,508 nc_per_parr is massive. 

parr0 %>% 
  group_by(rule1) %>% 
  summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]), 
            beneficiarios = sum(beneficiarios),
            ben_per_parr = sum(beneficiarios) / n(), 
            not_reached = sum(not_reached),
            nr_per_parr = sum(not_reached) / n(),
            nr_per_mun = sum(not_reached) / n_distinct(pcode2), 
            avg_org_count = mean(org_count),
            coverage_percent = sum(beneficiarios) / sum(poblacion_2019),
            percent_pobre = sum(pob_pobre) / sum(poblacion_2019),
            percent_urbana = sum(pob_urbana) / sum(poblacion_2019),
            densidad_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
            parroquias = n(),
            municipios = n_distinct(pcode2),
            parr_per_mun = n() / n_distinct(pcode2)) %>% 
  gather(key = variable, value = value, 2:ncol(.)) %>% 
  spread_(key = names(.)[1], value = 'value') %>% 
  arrange(factor(variable, levels = c("not_reached", "nr_per_parr", "nr_per_mun", "beneficiarios",
                                      "ben_per_parr",  "avg_org_count", "coverage_percent",
                                      "percent_pobre", "percent_urbana", "densidad_ppl_km2", 
                                      "parroquias", "parr_no_ben", "municipios", 
                                      "parr_per_mun"))) %>%  pander(big.mark = ",")



6. Reference Table

type or use slider to filter by categories or values; use arrows to sort; table preliminarily arranged in descending order of number of not reached

parr0 %>%
  select(-percent_total_ben) %>% 
  mutate(sector_count = rowSums(select(., ends_with("_ben"))!=0)) %>% 
  mutate(educacion_only = ifelse(educacion_ben > 0, "educacion", ""),
         nutricion_only = ifelse(nutricion_ben > 0, "nutricion", ""),
         salud_only = ifelse(salud_ben > 0, "salud",  ""),
         wash_only = ifelse(wash_ben > 0, "wash", ""),
         proteccion_only = ifelse(proteccion_ben > 0, "proteccion", ""),
         sectors_present = str_trim(paste0(educacion_only, " ", nutricion_only, " ", proteccion_only, " ", 
                                  salud_only, " ", wash_only))) %>% 
  mutate_at(vars(pob_pobre, not_reached, org_count, beneficiarios), ~(round(., digits = 0))) %>% 
  mutate_at(vars(percent_pobre, percent_urbana), ~(round(., digits = 2))) %>% 
  select(estado, municipio, parroquia,  
         percent_pobre, percent_urbana, not_reached, beneficiarios, tree_node = rule3,
         org_count, sector_count, sectors_present, pcode3) %>% 
  arrange(desc(not_reached)) %>% 
  # the js is adjusting the font size for the whole container -- there doesn't seem to be another way
  datatable(filter = "top", options = list(pageLength = 10, scrollX = TRUE,
                                           initComplete = htmlwidgets::JS(
          "function(settings, json) {",
          paste0("$(this.api().table().container()).css({'font-size': '", "8.5pt", "'});"),
          "}")
       ) 
     ) 
LS0tDQp0aXRsZTogIkNvdmVyYWdlIGFuZCBnYXBzIGluIHRoZSBodW1hbml0YXJpYW4gcmVzcG9uc2UgaW4gVmVuZXp1ZWxhIGluIDIwMTkiDQphdXRob3I6ICJTZWFuIE5nIg0KZGF0ZTogIjI1LzExLzIwMjEiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICB0aGVtZTogcmVhZGFibGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgIA0KLS0tDQoNCjxzdHlsZT4NCiAgICBib2R5IC5tYWluLWNvbnRhaW5lciB7DQogICAgICAgIG1heC13aWR0aDogMTI4MHB4Ow0KICAgIH0NCjwvc3R5bGU+DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGg9OSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShzdHJpbmdpKQ0KbGlicmFyeShzdHJpbmdyKQ0KDQpsaWJyYXJ5KHBhbmRlcikNCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShnZ2ZvcmNlKQ0KbGlicmFyeShnZ3B1YnIpDQpsaWJyYXJ5KGZvcmNhdHMpDQpsaWJyYXJ5KHBhdGNod29yaykNCg0KbGlicmFyeShyYXR0bGUpDQpsaWJyYXJ5KHJwYXJ0KQ0KbGlicmFyeShycGFydC5wbG90KQ0KbGlicmFyeShycGFydC51dGlscykNCmxpYnJhcnkocGFydHlraXQpDQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShmYWN0b2V4dHJhKQ0KbGlicmFyeShzaGlueSkNCg0KbGlicmFyeShnZ21hcCkNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KHJtYXBzaGFwZXIpDQpsaWJyYXJ5KHZpcmlkaXMpDQoNCiMgZGlzYWJsaW5nIHNjaWVudGlmaWMgbm90YXRpb24NCm9wdGlvbnMoc2NpcGVuID0gMTAwKQ0KDQojIHBhbmRlciB0YWJsZXMgYWxsIGluIG9uZSByb3cNCnBhbmRlck9wdGlvbnMoJ3RhYmxlLnNwbGl0LnRhYmxlJywgSW5mKQ0KDQojIHBhbmRlciB0aG91c2FuZHMgc2VwYXJhdG9yDQpwYW5kZXJPcHRpb25zKCJiaWcubWFyayIsICIsIikNCg0KYCVvdXQlYCA8LSBOZWdhdGUoYCVpbiVgKQ0KDQojIGZ1bmN0aW9uIHRvIHJlbW92ZSBhY2NlbnRzIA0Kcm1fYWNjZW50IDwtIGZ1bmN0aW9uKGNvbG5zKXsNCiAgY29sbnMgPC0gc3RyaV90cmFuc19nZW5lcmFsKGNvbG5zLCAiTGF0aW4tQVNDSUkiKQ0KfQ0KDQpgYGANCg0KIyMgMS4gSW50cm9kdWN0aW9uDQoNClRoaXMgYXV0b21hdGVkIHJlcG9ydGVkIGlzIGludGVuZGVkIHRvIHNlcnZlIGFzIGEgdGVtcGxhdGUgZm9yIGEgKipjb3ZlcmFnZSBhbmQgZ2FwcyBhbmFseXNpcyouIEl0IHByb3ZpZGVzIGV4YW1wbGVzIG9mIHRoZSBhbmFseXNlcyBuZWNlc3NhcnkgdG8gaWRlbnRpZnkgcG9wdWxhdGlvbnMgaW4gbmVlZCB3aG8gYXJlIG5vdCBjdXJyZW50bHkgY292ZXJlZCBieSBodW1hbml0YXJpYW4gYWN0aW9uIGFuZCBwcm92aWRlIHJlY29tbWVuZGF0aW9ucyBvbiBob3cgcGFydG5lcnMgbWF5IGJlc3QgcmVhY2ggdGhlbS4gQ292ZXJhZ2UgYW5kIGdhcHMgYW5hbHlzZXMgc2hvdWxkIGJlIGNvb3JkaW5hdGVkIHdpdGggbW9uaXRvcmluZyBhbmQgZXZhbHVhdGlvbiAoTSZFKSBhY3Rpdml0aWVzLCBhbmQgb3Bwb3J0dW5pdGllcyB3aGVyZSBJbmZvcm1hdGlvbiBNYW5hZ2VtZW50IGFuZCBNJkUgbWF5IHJlaW5mb3JjZSBlYWNoIG90aGVyIGFyZSBtZW50aW9uZWQgYmVsb3csIGluIHRoZSByZWxldmFudCBzZWN0aW9ucy4gDQoNCkNvdmVyYWdlIGFuZCBnYXBzIGFuYWx5c2VzIGFyZSBrZXkgZG9jdW1lbnRzLCBidXQgYXJlIGFsc28gcmFyZWx5IHRha2VuIGludG8gYWNjb3VudCBkdXJpbmcgb3BlcmF0aW9uYWwgcGxhbm5pbmcgb3IgcmVmZXJlbmNlZCBkdXJpbmcgcmV2aXNpb25zIG9mIG1ham9yIHN0cmF0ZWdpYyBkb2N1bWVudHMsIHN1Y2ggYXMgSHVtYW5pdGFyaWFuIFJlc3BvbnNlIFBsYW5zIChIUlBzKS4gTmVpdGhlciBhcmUgdGhleSBtZW50aW9uZWQgaW4gT0NIQSdzIEhSUCBndWlkYW5jZS4gDQoNCkdpdmVuIHRoYXQgbmVlZHMgYWx3YXlzIGdyb3NzbHkgb3V0d2VpZ2ggYXZhaWxhYmxlIGZ1bmRpbmcsIGl0IHN0aWxsIHJlbWFpbnMgYW4gaW5kdXN0cnktd2lkZSBjaGFsbGVuZ2UgdG8gcmVzcG9uZCBhZGVxdWF0ZWx5IHRvIGdhcHMgaW4gY292ZXJhZ2UgYW5kIHJlYWxsb2NhdGUgcmVzb3VyY2VzIGFjY29yZGluZ2x5LiBUb28gb2Z0ZW4sIG9uY2UgY29tbWl0dGVkIHRvIGEgY291cnNlIG9mIGFjdGlvbiwgY2x1c3RlcnMgYW5kIHRoZWlyIGh1bWFuaXRhcmlhbiBwYXJ0bmVycyBkbyBub3QgcmUtZXhhbWluZSBvciByZS1ldmFsdWF0ZSB0aGVpciBpbnRlcnZlbnRpb25zLiBUaGUgYW5hbHlzZXMgc2hvd24gYmVsb3cgYXJlIG5vdCBjb21wbGljYXRlZCBhbmQgdGhleSBoYXZlIGFsbCBiZWVuIHBlcmZvcm1lZCBieSBhIHNpbmdsZSBhbmFseXN0OyB5ZXQsIHRoaXMgdHlwZSBvZiByZXBvcnQgcmVtYWlucyBleGNlZWRpbmdseSByYXJlLiANCg0KDQojIyMjIEEgbm90ZSBvbiB0aGUgZGF0YQ0KDQoqIE1vc3Qgb2YgdGhlIGRhdGEgb3JpZ2luYXRlcyBmcm9tIHRoZSBFZHVjYXRpb24sIEhlYWx0aCwgTnV0cml0aW9uLCBQcm90ZWN0aW9uIGFuZCBXQVNIIENsdXN0ZXJzLCBmcm9tIE1heSB0byBPY3RvYmVyIDIwMTkgLS0gYW5kIGFueSBjb25jbHVzaW9ucyBvciBhbmFseXNpcyBhcmUgYm91bmRlZCBieSB0aGlzIHRpbWUgcGVyaW9kIGFuZCBpbGx1c3RyYXRpdmUgb2YgdGhlIHJlc3BvbnNlIGFzIGl0IHdhcyBpbiBOb3ZlbWJlciAyMDE5LiBQYXJ0bmVyIGRhdGEgaGFzIGJlZW4gYW5vbnltaXNlZC4gT3RoZXIgZGF0YSBvcmlnaW5hdGUgZnJvbSB0aGUgY2Vuc3VzIGRhdGFzZXQgb2YgVmVuZXp1ZWxhIHRoYXQgd2FzIG1haW50YWluZWQgYnkgVU5JQ0VGLiBVbmxpa2UgdGhlIGRvY3VtZW50IG9mIDVXIHJlcG9ydGluZyBhbmQgY2xlYW5pbmcsIHdlIHdpbGwgbm90IGJlIGV4cGxvcmluZyB0aGUgY2xlYW5pbmcgcHJvY2Vzcy4gQnV0IHRoZSBzb3VyY2UgY29kZSBvZiBlYWNoIGNodW5rIHdpbGwgYmUgZGlzcGxheWVkIHdoZW4gdGhlIGBDb2RlYCBidXR0b24gaXMgY2xpY2tlZC4gDQoNCmBgYHtyIHJlYWRpbmctYW5kLWNsZWFuaW5nLWFuZC1pbnRlcm1lZGl0ZS1vdXB1dHN9DQoNCiMgcmVhZGluZyBhbmQgY2xlYW5pbmcgLS0geW91IHJlYWxseSBzaG91bGQgYnJlYWsgaXQgaW50byBwYXJ0cw0KdmVuMSA8LSByZWFkX2NzdigiY29uc29saWRhdGlvbiAxOTEyMDkgMTYzNi5jc3YiKSAlPiUgDQogIGNsZWFuX25hbWVzKCkgJT4lIA0KICAjIHJlbW92aW5nIHVudXNlZCBjb2x1bW5zDQogIHNlbGVjdCgtYyhjb2RpZ29kZWVzdGFibGVjaW1pZW50b29jZW50cm8sIGxvY19pZCwgaHJwX3NpdHJlX3BfaW5kaWNhdG9yLCANCiAgICAgICAgICAgIHRpcG9kZXJlc3B1ZXN0YSwgY29tZW50YXJpb3MsIGNvb3JkZWFkYXNfZ3BzX3gsIGNvb3JkZWFkYXNfZ3BzX3ksDQogICAgICAgICAgICBmZWNoYWRlX2luaWNpbywgZmVjaGFfcHJldmlzdGFkZV9maW5hbGl6YWNpb24pKSAlPiUgDQogICMgcmVuYW1pbmcgdW53aWVsZHkgY29sdW1ucyANCiAgcmVuYW1lKHViaWNhY2lvbiAgICAgICAgICA9IGNvbXVuaWRhZG9ub21icmVkZWxlc3RhYmxlY2ltaWVudG9fY2VudHJvLCANCiAgICAgICAgIHNlY3RvciAgICAgICAgICAgICA9IHNlY3Rvcl9hcmVhZGVfcmVzcG9uc2FiaWxpYWQsDQogICAgICAgICBiZW5lZmljaWFyaW9zX21ldGEgPSBiZW5lZmljaWFyaW9zX21ldGFfbnVtZXJvZGVwZXJzb25hcywNCiAgICAgICAgIGVzdGF0dXMgICAgICAgICAgICA9IGVzdGF0dXNkZXByb2dyYW1hY2lvbikgJT4lIA0KICAgICAgIyBtdXRhdGluZyB0aGUgZGF0ZSB0byB0aGUgcmlnaHQgZm9ybWF0DQogIG11dGF0ZShtb250aCA9IGFzLmZhY3RvcihyZWNvZGUobW9udGgsDQogICAgICAgICAgICAgICAgICAgICAgICBgNGAgPSAiMzAvMDQvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgNWAgPSAiMzEvMDUvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgNmAgPSAiMzAvMDYvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgN2AgPSAiMzEvMDcvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgOGAgPSAiMzEvMDgvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgOWAgPSAiMzAvMDkvMjAxOSIsDQogICAgICAgICAgICAgICAgICAgICAgICBgMTBgID0gIjMxLzEwLzIwMTkiKSkpICU+JSANCiAgbXV0YXRlKG1vbnRoID0gYXMuRGF0ZShtb250aCAlPiUgc3RycHRpbWUoLiwgZm9ybWF0ID0gIiVkLyVtLyVZIikpKSAlPiUgDQogIG11dGF0ZShvcmdfbGlkZXIgPSBjb2FsZXNjZShvcmdfbGlkZXIsIG9yZ19pbXBsZW1lbnRhZG9yYSkpICU+JSANCiAgIyBjb3JyZWN0aW5nIHNlY3RvciBuYW1lcw0KICBtdXRhdGUoc2VjdG9yID0gc3RyX3JlcGxhY2VfYWxsKHNlY3RvciwgYygNCiAgICAiQWd1YV9zYW5lYW1pZW50b19oaWdpZW5lIiAgICAgICAgICAgID0gIldBU0giLA0KICAgICJlZHVjYWNpb24iICAgICAgICAgICAgICAgICAgICAgICAgICAgPSAiRWR1Y2FjaW9uIiwNCiAgICAiTnV0cmljaW9uIiAgICAgICAgICAgICAgICAgICAgICAgICAgID0gIk51dHJpY2lvbiIsDQogICAgInByb3RlY2Npw7NuX05pw7Fvc19OacOxYXNfQWRvbGVzY2VudGVzIiA9ICJQcm90ZWNjaW9uX05OQSIsDQogICAgIlByb3RlY2Npw7NuX05pw7Fvc19OacOxYXNfQWRvbGVzY2VudGVzIiA9ICJQcm90ZWNjaW9uX05OQSIsDQogICAgIlByb3RlY2Npw7NuX1Zpb2xlbmNpYV9Hw6luZXJvIiAgICAgICAgID0gIlByb3RlY2Npb25fR0JWIikpKSAlPiUgDQogICMgcmVuYW1pbmcgYmVuZWZpY2lhcnkgZGlzYWdncmVnYXRpb24gY29sdW1ucyANCiAgcmVuYW1lKGZfMF8xOCA9IGZfMTgsDQogICAgICAgICBtXzBfMTggPSBtXzE4LA0KICAgICAgICAgZl8xOHBsdXMgPSBmXzE4XzIsDQogICAgICAgICBtXzE4cGx1cyA9IG1fMThfMikgJT4lIA0KICBtdXRhdGUoZXN0YWRvICAgID0gcm1fYWNjZW50KHN0cl90b191cHBlcihlc3RhZG8pKSwgDQogICAgICAgICBtdW5pY2lwaW8gPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKG11bmljaXBpbykpLA0KICAgICAgICAgcGFycm9xdWlhID0gcm1fYWNjZW50KHN0cl90b191cHBlcihwYXJyb3F1aWEpKSwNCiAgICAgICAgIHViaWNhY2lvbiA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIodWJpY2FjaW9uKSksDQogICAgICAgICBhY3RpdmlkYWQgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKGFjdGl2aWRhZCkpLA0KICAgICAgICAgY2F0ZWdvcmlhID0gcm1fYWNjZW50KHN0cl90b191cHBlcihjYXRlZ29yaWFkZWFjdGl2aWRhZCkpKSAlPiUgDQogICMgcmVjb2RpbmcgdGhlIGVzdGF0dXMgY29sdW1uIA0KICBtdXRhdGUoZXN0YXR1cyA9IHN0cl9yZXBsYWNlX2FsbChlc3RhdHVzLCANCiAgICAgICAgICAgICAgICAgIGMoIkVuIGVqZWN1Y2lvbiIgPSAiZWplY3VjaW9uIiwgDQogICAgICAgICAgICAgICAgICAgICJlbiBlamVjdWNpw7NuIiA9ICJlamVjdWNpb24iLCANCiAgICAgICAgICAgICAgICAgICAgImVuIEVqZWN1Y2nDs24iID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICJFbiBlamVjdWNpw7NuIiA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiRW4gRWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwNCiAgICAgICAgICAgICAgICAgICAgIkVuZWplY3VjacOzbiIgID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICI0Mzc0MSIgICAgICAgID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICJmaW5hbGl6YWRhIiA9ICJmaW5hbGl6YWRhIiwNCiAgICAgICAgICAgICAgICAgICAgIkZpbmFsaXphZGEiID0gImZpbmFsaXphZGEiLA0KICAgICAgICAgICAgICAgICAgICAiUGxhbmVhZGEiID0gInBsYW5lYWRhIiwNCiAgICAgICAgICAgICAgICAgICAgInBsYW5lYWRhIGNvbiBmaW5hbmNpYW1pZW50byIgPSAicGxhbmVhZGEiLA0KICAgICAgICAgICAgICAgICAgICAicGxhbmVhZGEgc2luIGZpbmFuY2lhbWllbnRvIiA9ICJwbGFuZWFkYSIpKSkgJT4lIA0KICByZXBsYWNlX25hKGxpc3QoZXN0YXR1cyA9ICJlamVjdWNpb24iKSkgJT4lIA0KICAjIHJlbW92aW5nIGFsbCBwbGFubmVkIGFjdGl2aXRpZXMgDQogIGZpbHRlcihlc3RhdHVzICE9ICJwbGFuZWFkYSIpICU+JSANCiAgZmlsdGVyKHN0cl9kZXRlY3QocGNvZGUzLCAiXlZFIikpICU+JSAjIGRlY2lkZSBpZiB5b3Ugd2FudCB0byBkbyB0aGlzIGhlcmUgb3IgbGF0ZXINCiAgc2VsZWN0KC1jKDIzOjkyKSkNCg0KIyBJJ20ga2luZGEgZG91YnRpbmcgdGhlIHVzZSBvZiB1X2JlbiwgeWEgSSB0aGluayB0YWtlIGl0IG91dD8gc2luY2UgeW91J3JlIG9ubHkgdXNpbmcgaXQgb25jZQ0KIyBBbSBJIGp1c3QgbWFraW5nIHRoZXNlIG91dCBvZiBoYWJpdD8gSSBjb3VsZCBtYWtlIHRoZW0gaW5zaWRlIHRoZSANCiMgY29kZSBjaHVuayBmb3IgcGFyciwgYnV0IG1heWJlIEkgY2FuIGZpbmQgc29tZSBqdXN0aWZpY2F0aW9uIGZvciB0aGVpciBleGlzdGVuY2UsIA0KIyBtYXliZSB0aGUgZGlzYWdncmVnYXRpb25zPyANCg0KIyBWYWNjaW5hdGlvbiBhY3Rpdml0aWVzIGZpbHRlcmVkIG91dA0KdV9iZW4gPC0gdmVuMSAlPiUgDQogIHBpdm90X2xvbmdlcihmXzBfMTg6bV8xOHBsdXMsIG5hbWVzX3RvID0gImRlc2FncmVnYWNpb24iLCB2YWx1ZXNfdG8gPSAiYmVuZWZpY2lhcmlvcyIpICU+JSANCiAgZmlsdGVyKGNhdGVnb3JpYWRlYWN0aXZpZGFkICE9ICJWYWN1bmFjaW9uIikgJT4lIA0KICBmaWx0ZXIoYmVuZWZpY2lhcmlvcyAhPSAwKSAlPiUgDQogIGdyb3VwX2J5KHViaWNhY2lvbiwgZGVzYWdyZWdhY2lvbikgJT4lIA0KICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpDQoNCmFjdF9iZW4gPC0gdmVuMSAlPiUgDQogIHBpdm90X2xvbmdlcihmXzBfMTg6bV8xOHBsdXMsIG5hbWVzX3RvID0gImRlc2FncmVnYWNpb24iLCB2YWx1ZXNfdG8gPSAiYmVuZWZpY2lhcmlvcyIpICU+JSANCiAgZmlsdGVyKGJlbmVmaWNpYXJpb3MgIT0gMCkgJT4lIA0KICBncm91cF9ieSh1YmljYWNpb24sIGRlc2FncmVnYWNpb24sIGFjdGl2aWRhZCkgJT4lIA0KICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgbXV0YXRlKHNlY3RvciA9IGlmZWxzZShzdHJfZGV0ZWN0KHNlY3RvciwgIlByb3RlY2Npb25fR0JWfFByb3RlY2Npb25fR2VuZXJhbHxQcm90ZWNjaW9uX05OQSIpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAiUHJvdGVjY2lvbiIsIHNlY3RvcikpDQoNCiMgcmJpbmQoc3VtKHVfYmVuJGJlbmVmaWNpYXJpb3MpLCANCiMgICAgICAgc3VtKGFjdF9iZW4kYmVuZWZpY2lhcmlvcyksIA0KIyAgICAgICBzdW0odV9iZW4kYmVuZWZpY2lhcmlvcykgLSBzdW0oYWN0X2JlbiRiZW5lZmljaWFyaW9zKSkNCg0KYGBgDQoNCg0KDQpgYGB7ciBtYWtpbmctYWxsLXBhcnItYW5kLXBhcnIwfQ0KIyBJIHRoaW5rIHRoaXMgaXMgYSBnaWdhbnRpYyBjaHVuayAtLSBjYW5ub3QgZGVjaWRlIGlmIEkgd291bGQgcmF0aGVyIGhhdmUgbGVzcyB0aGluZ3MgaW4gdGhlIA0KIyBlbnZpcm9ubWVudCBvciBpZiBJIHdhbnQgbW9yZSByZWFkYWJsZSBjaHVua3MuIFRoZSBiZW5lZml0IGhlcmUgSSBndWVzcyBpcyB0aGF0IGlmIEkgd2FudCB0byBjaGFuZ2Ugc29tZXRoaW5nLCBJIGp1c3QgaGF2ZSB0byBjb21lIHRvIHRoaXMgY2h1bmsNCg0KcGFyciA8LSB1X2JlbiAlPiUgDQogIGdyb3VwX2J5KHBjb2RlMykgJT4lIA0KICBzdW1tYXJpc2UoYmVuZWZpY2lhcmlvcyA9IHN1bShiZW5lZmljaWFyaW9zKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICAjIGNvdW50IG9mIG9yZ2FuaXNhdGlvbnMgcGVyIHBjb2RlMw0KICBsZWZ0X2pvaW4oYWN0X2JlbiAlPiUgDQogICAgICAgICAgICAgIyBmaWx0ZXIoY2F0ZWdvcmlhICE9ICJWYWN1bmFjaW9uIikgJT4lDQogICAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUzKSAlPiUgDQogICAgICAgICAgICAgc3VtbWFyaXNlKG9yZ19jb3VudCA9IG5fZGlzdGluY3Qob3JnX2ltcGxlbWVudGFkb3JhKSkpICU+JSANCiAgIyBnZXR0aW5nIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzLCBzZWN0b3IgY291bnQgYW5kIG1heGltdW0gbXVsdGktc2VjdG9yIGJlbmVmaWNpYXJpZXMNCiAgbGVmdF9qb2luKGFjdF9iZW4gJT4lDQogICMgdmFjY2luYXRpb24gZmlsdGVyZWQgb3V0ICANCiAgIGZpbHRlcihjYXRlZ29yaWFkZWFjdGl2aWRhZCAhPSAiVmFjdW5hY2lvbiIpICU+JSANCiAgICAgICAgICAgICBncm91cF9ieSh1YmljYWNpb24sIGRlc2FncmVnYWNpb24sIHNlY3RvcikgJT4lIA0KICAgICAgICAgICAgICAgICBzbGljZSh3aGljaC5tYXgoYmVuZWZpY2lhcmlvcykpICU+JSANCiAgICAgICAgICAgICAgICAgdW5ncm91cCgpICU+JQ0KICAgICAgICAgICAgICAgICBncm91cF9ieSh1YmljYWNpb24sIHNlY3RvciwgcGNvZGUzKSAlPiUgDQogICAgICAgICAgICAgICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBzZWN0b3IsIHZhbHVlc19mcm9tID0gYmVuZWZpY2lhcmlvcykgJT4lIA0KICAgICAgICAgICAgICAgICByZXBsYWNlX25hKGxpc3QoTnV0cmljaW9uID0gMCwgRWR1Y2FjaW9uID0gMCwgV0FTSCA9IDAsIFNhbHVkID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlZ3VyaWRhZF9BbGltZW50YXJpYSA9IDAsIFByb3RlY2Npb24gPSAwKSkgJT4lDQogICAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUzLCBkZXNhZ3JlZ2FjaW9uKSAlPiUgDQogICAgICAgICAgICAgc3VtbWFyaXNlKG51dHJpY2lvbl9iZW4gICA9IHN1bShOdXRyaWNpb24pLA0KICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWNjaW9uX2JlbiAgPSBzdW0oUHJvdGVjY2lvbiksDQogICAgICAgICAgICAgICAgICAgICAgIHdhc2hfYmVuICAgICAgICA9IHN1bShXQVNIKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2FsdWRfYmVuICAgICAgID0gc3VtKFNhbHVkKSwNCiAgICAgICAgICAgICAgICAgICAgICAgZWR1Y2FjaW9uX2JlbiAgID0gc3VtKEVkdWNhY2lvbiksDQogICAgICAgICAgICAgICAgICAgICAgIHNhX2JlbiAgICAgICAgICA9IHN1bShTZWd1cmlkYWRfQWxpbWVudGFyaWEpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUgDQogICAgICAgICAgICAgbXV0YXRlKGJlbl9mcmVxICAgID0gbnV0cmljaW9uX2JlbiArIHByb3RlY2Npb25fYmVuICsgd2FzaF9iZW4gKyBzYWx1ZF9iZW4gKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWR1Y2FjaW9uX2JlbiArIHNhX2JlbiwNCiAgICAgICAgICAgICAgICAgICAgc2VjX2Jlbl9tYXggPSBwbWF4KG51dHJpY2lvbl9iZW4sIHByb3RlY2Npb25fYmVuLCB3YXNoX2JlbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX2JlbiwgZWR1Y2FjaW9uX2Jlbiwgc2FfYmVuKSwNCiAgICAgICAgICAgICAgICAgICAgbXNfYmVuX21heCAgPSBpZmVsc2Uoc2VjX2Jlbl9tYXggPj0gYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VjX2Jlbl9tYXgpKSAlPiUgDQogICAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUzKSAlPiUgDQogICAgICAgICAgICAgc3VtbWFyaXNlKG51dHJpY2lvbl9iZW4gID0gc3VtKG51dHJpY2lvbl9iZW4pLA0KICAgICAgICAgICAgICAgICAgICAgICBwcm90ZWNjaW9uX2JlbiA9IHN1bShwcm90ZWNjaW9uX2JlbiksDQogICAgICAgICAgICAgICAgICAgICAgIHdhc2hfYmVuICAgICAgID0gc3VtKHdhc2hfYmVuKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2FsdWRfYmVuICAgICAgPSBzdW0oc2FsdWRfYmVuKSwNCiAgICAgICAgICAgICAgICAgICAgICAgZWR1Y2FjaW9uX2JlbiAgPSBzdW0oZWR1Y2FjaW9uX2JlbiksDQogICAgICAgICAgICAgICAgICAgICAgIHNhX2JlbiAgICAgICAgID0gc3VtKHNhX2JlbiksDQogICAgICAgICAgICAgICAgICAgICAgIGJlbl9mcmVxICAgPSBzdW0oYmVuX2ZyZXEpLA0KICAgICAgICAgICAgICAgICAgICAgICBzZWNfYmVuX21heCAgICA9IHN1bShzZWNfYmVuX21heCksDQogICAgICAgICAgICAgICAgICAgICAgIG1zX2Jlbl9tYXggPSBzdW0obXNfYmVuX21heCkpICU+JSANCiAgICAgICAgICAgICBtdXRhdGUoc2VjdG9yX2NvdW50ID0gcm93U3VtcyhzZWxlY3QoLiwgZW5kc193aXRoKCJfYmVuIikpICE9IDApKSkgJT4lICANCiAgZmlsdGVyKHN0cl9kZXRlY3QocGNvZGUzLCAiXlZFIikpICU+JSANCiAgIyByaWdodF9qb2luIHRvIHRoZSBjZW5zdXMgZGF0YQ0KICByaWdodF9qb2luKHJlYWRfZXhjZWwoImNlbnN1cyBkYXRhIDIwMTkxMTIyLnhsc3giLCBzaGVldCA9ICJkYXRhIikgJT4lIA0KICAgICAgICBjbGVhbl9uYW1lcygpICU+JSANCiAgICAgICAgIyBzZWxlY3RpbmcgdmFyaWFibGVzIGFuZCByZW5hbWluZyB0aGVtIHdpdGggc2VsZWN0DQogICAgICAgIHNlbGVjdChlc3RhZG8sIHBjb2RlMSwgbXVuaWNpcGlvLCBwY29kZTIsIHBhcnJvcXVpYSwgcGNvZGUzLCANCiAgICAgICAgICAgICAgIGZvID0gZmllbGRfb2ZmaWNlLA0KICAgICAgICAgICAgICAgcG9ibGFjaW9uXzIwMTkgPSB4XzIwMTlfcG9ibGFjaW9uX3BhcnJvcXVpYWxfdG90YWwsDQogICAgICAgICAgICAgICBob2dhcmVzXzIwMTEgPSBudW1lcm9fZGVfaG9nYXJlcywgDQogICAgICAgICAgICAgICBoYW1fMjAxOV9hbWJpdG9zX2dlLCANCiAgICAgICAgICAgICAgIHBlcmNlbnRfcG9icmUgPSBoYW1fMjAxOV94eF9wb2JyZXphX2Vudl9wb3JfcGFycm9xdWlhLCANCiAgICAgICAgICAgICAgIHBvYl9wb2JyZSA9IGhhbV8yMDE5X3h4X3BvYmxhY2lvbl9wb2JyZV9wb3JfcGFycm9xdWlhLCANCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl90b3RhbF8yMDExLA0KICAgICAgICAgICAgICAgcG9ibGFjaW9uX2luZmFudGlsX21lbm9yX2RlXzEyX2Fub3MsIHBvYmxhY2lvbl9hZG9sZXNjZW50ZXNfZGVfMTJfYV8xN19hbm9zLA0KICAgICAgICAgICAgICAgcG9ibGFjaW9uX2RlXzE4X2Fub3NfeV9tYXMsIA0KICAgICAgICAgICAgICAgcGVyY2VudF91cmJhbmEgPSBwb2JsYWNpb25fdXJiYW5hX3BlcmNlbnQsIA0KICAgICAgICAgICAgICAgYXJlYV9rbTIsIA0KICAgICAgICAgICAgICAgZGVuc2lkYWRfcHBsX2ttMiA9IGRlbnNpZGFkX3BvYmxhY2lvbmFsX3BwbF9rbTIsDQogICAgICAgICAgICAgICBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCwgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhLCANCiAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9tZWRpYSwgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwsDQogICAgICAgICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MsIA0KICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgPSB4X2FiYXN0X2FndWEyX3BlcmNlbnRfc2luX2FndWFfc2VndXJhLA0KICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gPQ0KICAgICAgICAgICAgICAgICB4X3NhbmVhbWllbnRvX3BlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvLA0KICAgICAgICAgICAgICAgcGVyY2VudF9hbmFsZmFiZXRvID0gcGVyY2VudF9wb2JsYWNpb25fMTBfYW5vc195X21hc19hbmFsZmFiZXRhLA0KICAgICAgICAgICAgICAgcHJvbWVkaW9fZGVfcGVyc29uYXNfcG9yX3ZpdmllbmRhLA0KICAgICAgICAgICAgICAgcGVyY2VudF9ob2dhcmVzX2plZmF0dXJhX2ZlbWVuaW5hID0gcGVyY2VudF9kZV9ob2dhcmVzX2Nvbl9qZWZhdHVyYV9mZW1lbmluYSwNCiAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyA9DQogICAgICAgICAgICAgICAgIHNlcnZpY2lvX2VsZWN0cmljb19wZXJjZW50X25vX3RpZW5lX3NlcnZpY2lvX2VsZWN0cmljbywNCiAgICAgICAgICAgICAgIGhhbV8yMDE5X3hfdmlvbGVuY2lhX2VudmVsb3BlLCBoYW1fMjAxOV94X21vcnRhbGlkYWRfeV9zYWx1ZF9lbnZlbG9wZSwgDQogICAgICAgICAgICAgICBoYW1fMjAxOV94X3BvYnJlemFfZW52ZWxvcGUsIHByb21lZGlvX2RlX2VkYWQpICU+JSANCiAgICAgICAgbXV0YXRlKGVzdGFkbyAgICAgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKGVzdGFkbykpLCAjIGp1c3QgdG8gbWFrZSBzdXJlIA0KICAgICAgICAgICAgICAgbXVuaWNpcGlvICA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIobXVuaWNpcGlvKSksDQogICAgICAgICAgICAgICBwYXJyb3F1aWEgID0gcm1fYWNjZW50KHN0cl90b191cHBlcihwYXJyb3F1aWEpKSkgJT4lIA0KICAgICAgICAjIGNyZWF0aW5nIG5ldyBkaXNhZ2dyZWdhdGlvbiB2YXJpYWJsZXMgDQogICAgICAgIG11dGF0ZShwb2JfbWVub3JfZGVfMTggPSAocG9ibGFjaW9uX2luZmFudGlsX21lbm9yX2RlXzEyX2Fub3MgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9ibGFjaW9uX2Fkb2xlc2NlbnRlc19kZV8xMl9hXzE3X2Fub3MpIC9wb2JsYWNpb25fdG90YWxfMjAxMSAqDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2JsYWNpb25fMjAxOSwgDQogICAgICAgICAgICAgICBwb2JfMThfeV9tYXMgICAgPSBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcyAvIHBvYmxhY2lvbl90b3RhbF8yMDExICogcG9ibGFjaW9uXzIwMTksIA0KICAgICAgICAgICAgICAgaG9nYXJlc18yMDE5ICAgID0gaG9nYXJlc18yMDExICogcG9ibGFjaW9uXzIwMTkgLyBwb2JsYWNpb25fdG90YWxfMjAxMSwgDQogICAgICAgICAgICAgICBtYXRyaWN1bGFfdG90YWwgPSBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fbWVkaWEpICU+JSANCiAgICAgICAgIyBkaXZpZGluZyBjb2x1bW5zIGJ5IDEwMCBzbyB0aGF0IHRoZXkncmUgYmV0d2VlbiAwIGFuZCAxDQogICAgICAgIG11dGF0ZV9hdCh2YXJzKHBlcmNlbnRfYW5hbGZhYmV0bywgcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvLCANCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEsDQogICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvLA0KICAgICAgICAgICAgICAgICAgICAgICBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIHBlcmNlbnRfdXJiYW5hLA0KICAgICAgICAgICAgICAgICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCksIH4oLiAvIDEwMCkpICU+JSANCiAgICAgICAgIyBtdXRhdGluZyBuZXcgY29sdW1ucyB3aXRoIHBvcHVsYXRpb25zDQogICAgICAgIG11dGF0ZShwb2JfYW5hbGZhYmV0byAgICAgICAgICAgICAgID0gcGVyY2VudF9hbmFsZmFiZXRvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX2FndWFfc2VndXJhICAgICAgICAgID0gcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKiBwb2JsYWNpb25fMjAxOSwgDQogICAgICAgICAgICAgICBwb2Jfc2luX3NlcnZpY2lvX2VsZWN0cmljbyAgID0gcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX3NhbmVhbWllbnRvX21lam9yYWRvID0gcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKiBwb2JsYWNpb25fMjAxOSwNCiAgICAgICAgICAgICAgIHBvYl91cmJhbmEgICAgICAgICAgICAgICAgICAgPSBwZXJjZW50X3VyYmFuYSAqIHBvYmxhY2lvbl8yMDE5KSAlPiUgDQogICAgICAgIHNlbGVjdCgtYyhtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCwgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhLCANCiAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9tZWRpYSwgcG9ibGFjaW9uX3RvdGFsXzIwMTEsIGhvZ2FyZXNfMjAxMSwNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl9pbmZhbnRpbF9tZW5vcl9kZV8xMl9hbm9zLCBwb2JsYWNpb25fYWRvbGVzY2VudGVzX2RlXzEyX2FfMTdfYW5vcywgDQogICAgICAgICAgICAgICBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcykpLA0KICAgICAgICAgICAgYnkgPSAicGNvZGUzIikgJT4lIA0KICAjIG11dGF0aW5nIG5ldyB2YXJpYWJsZXMgYW5kIG1ha2luZyBzdXJlIE5BcyBiZWNvbWUgMHMgDQogIG11dGF0ZShiZW5lZmljaWFyaW9zICA9IGlmZWxzZShpcy5uYShiZW5lZmljaWFyaW9zKSwgMCwgYmVuZWZpY2lhcmlvcyksDQogICAgICAgICBvcmdfY291bnQgICAgICA9IGlmZWxzZShpcy5uYShvcmdfY291bnQpLCAwLCBvcmdfY291bnQpLA0KICAgICAgICAgc2VjdG9yX2NvdW50ICAgPSBpZmVsc2UoaXMubmEoc2VjdG9yX2NvdW50KSwgMCwgc2VjdG9yX2NvdW50KSwgDQogICAgICAgICBlZHVjYWNpb25fYmVuICA9IGlmZWxzZShpcy5uYShlZHVjYWNpb25fYmVuKSwgMCwgZWR1Y2FjaW9uX2JlbiksDQogICAgICAgICBudXRyaWNpb25fYmVuICA9IGlmZWxzZShpcy5uYShudXRyaWNpb25fYmVuKSwgMCwgbnV0cmljaW9uX2JlbiksDQogICAgICAgICBwcm90ZWNjaW9uX2JlbiA9IGlmZWxzZShpcy5uYShwcm90ZWNjaW9uX2JlbiksIDAsIHByb3RlY2Npb25fYmVuKSwNCiAgICAgICAgIHNhbHVkX2JlbiAgICAgID0gaWZlbHNlKGlzLm5hKHNhbHVkX2JlbiksIDAsIHNhbHVkX2JlbiksDQogICAgICAgICBzYV9iZW4gICAgICAgICA9IGlmZWxzZShpcy5uYShzYV9iZW4pLCAwLCBzYV9iZW4pLA0KICAgICAgICAgd2FzaF9iZW4gICAgICAgPSBpZmVsc2UoaXMubmEod2FzaF9iZW4pLCAwLCB3YXNoX2JlbiksDQogICAgICAgICBtc19iZW5fbWF4ICAgICA9IGlmZWxzZShpcy5uYShtc19iZW5fbWF4KSwgMCwgbXNfYmVuX21heCksDQogICAgICAgICBiZW5fZnJlcSAgICAgICA9IGlmZWxzZShpcy5uYShiZW5fZnJlcSksIDAsIGJlbl9mcmVxKSwNCiAgICAgICAgIG5vdF9yZWFjaGVkICAgICAgICAgICAgPSBwb2JfcG9icmUgLSBiZW5lZmljaWFyaW9zLA0KICAgICAgICAgY292ZXJhZ2VfcGVyY2VudCAgICAgICA9IGJlbmVmaWNpYXJpb3MgLyBwb2JsYWNpb25fMjAxOSwNCiAgICAgICAgIGNvdmVyYWdlX3BvYnJlX3BlcmNlbnQgPSBiZW5lZmljaWFyaW9zIC8gcG9iX3BvYnJlLA0KICAgICAgICAgcGVyY2VudF90b3RhbF9iZW4gICAgICA9IGJlbmVmaWNpYXJpb3MgLyBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICBtdWx0aXNlY3Rvcl9wZXJjZW50ICAgID0gbXNfYmVuX21heCAvIGJlbl9mcmVxLCANCiAgICAgICAgIG9yZ19wcmVzZW50ICAgICAgICAgICAgPSBpZmVsc2UoYmVuZWZpY2lhcmlvcyA+IDAsIFRSVUUsIEZBTFNFKSwNCiAgICAgICAgIHBvYl9wb2JyZV9zY29yZSAgICAgPSByZXNjYWxlKHBvYl9wb2JyZSwgdG8gPSBjKDAsMSkpLCANCiAgICAgICAgIHBlcmNlbnRfcG9icmVfc2NvcmUgPSByZXNjYWxlKHBlcmNlbnRfcG9icmUsIHRvID0gYygwLDEpKSwgDQogICAgICAgICBwb3ZlcnR5X3Njb3JlICAgICAgID0gKHBvYl9wb2JyZV9zY29yZSArIHBlcmNlbnRfcG9icmVfc2NvcmUpIC8gMikNCg0KIyB0YWtpbmcgYSBzdWJzZXQgb2YgcGFyciB0byBvbmx5IGdldCBwYXJyaXNoZXMgd2hlcmUgdGhlIG51bWJlciBvZiBiZW5lZmljaWFyaWVzIGRvZXMgbm90IGV4Y2VlZCB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucw0KDQpwYXJyMCA8LSBwYXJyICU+JSANCiAgZmlsdGVyKG5vdF9yZWFjaGVkID49IDEpICU+JSANCiAgbXV0YXRlKGdhcF9zY29yZSA9IChyZXNjYWxlKG5vdF9yZWFjaGVkLCB0byA9IGMoMCwxKSkgKyBwZXJjZW50X3BvYnJlX3Njb3JlKSAvIDIpDQoNCmBgYA0KDQpgYGB7ciB3cml0ZS1jc3YtcGFycjAsIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9IEZBTFNFfQ0KIyBldmFsbGVkIG91dCAtLSBjaGFuZ2UgdGhpcyBpZiB5b3Ugd2FudCB0aGUgY3N2IGZvciB0YWJsZWF1IG9yIHdoYXRldmVyDQp3cml0ZV9jc3YocGFycjAsICJwYXJyMC5jc3YiKQ0KYGBgDQoNCiMjIDIuIFN1bW1hcnkgb2YgY292ZXJhZ2UgYW5kIGdhcHMNCg0KIyMjIDJhLiBNYXAgb2YgcGFycmlzaGVzIGJ5IGdhcHMNCg0KYGBge3IgTUFQLVJFRiwgaW5jbHVkZSA9IEZBTFNFfQ0KIyByZWFkaW5nIGluIHRoZSBzaGFwZWZpbGUNCnBjb2RlM19zaGFwZSA8LSBzdF9yZWFkKCJDOi9Vc2Vycy9TZWFuIE5nL0RvY3VtZW50cy9SL2NvdmVyYWdlX2dhcHNfdmVuZXp1ZWxhL3Zlbl9hZG1ibmRhX2FkbTNfMjAxODA1MDIvdmVuX2FkbWJuZGFfYWRtM18yMDE4MDUwMi5zaHAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgcXVpZXQgPSBUUlVFKSAlPiUgDQogIHJlbmFtZShwY29kZTEgPSBBRE0xX1BDT0RFLA0KICAgICAgICAgcGNvZGUyID0gQURNMl9QQ09ERSwNCiAgICAgICAgIHBjb2RlMyA9IEFETTNfUENPREUpICU+JSANCiAgbXV0YXRlKHBjb2RlMyA9IHJlY29kZShwY29kZTMsDQogICAgICAgICAgICAgICAgICAgICAgICAgIlZFMDMwMTAyIiA9ICJWRTAzMDEwMSIsICMgb25seSBBbmFjbyBleGlzdHMsIGFjY29yZGluZyB0byB0aGUgY2Vuc3VzDQogICAgICAgICAgICAgICAgICAgICAgICAgIlZFMDMxOTAxIiA9ICJWRTAzMTkwMCIsICMgc29tZWhvdyB0aGUgY2Vuc3VzIGFuZCB0aGUgc2hhcGVmaWxlcyBjb25mbGljdA0KICAgICAgICAgICAgICAgICAgICAgICAgICJWRTA3MDMwMSIgPSAiVkUwNzAzMDAiKSkgJT4lICAjIGhlcmUgdG9vDQojIHNpbXBseWluZyB0byByZW1vdmUgc2xpdmVycyAtLSBsZXQncyBzZWUgaWYgdGhpcyB3b3JrcyANCiMgaXQncyBhIGJpdCBhYnN0cmFjdCBhdCAwLjA1LCBidXQgdGhlIHNsaXZlcnMgQVJFIGdvbmUgYW5kIGl0IGxvb2tzIG5vdCBiYWQgDQojIGZpZ3VyaW5nIHRoaXMgb3V0IHdhcyBtYWRkZW5pbmcsIEkgY2FuJ3QgYmVsaWV2ZSB5b3Ugc3BlbnQgc28gbG9uZyBvbiBjb3NtZXRpYyBpdGVtcyANCiAgbXNfc2ltcGxpZnkoa2VlcCA9IDAuMDUsIGtlZXBfc2hhcGVzID0gVFJVRSkNCg0KYGBgDQoNCmBgYHtyIGNvdmVyYWdlLW1hcC1ub3QtY292ZXJlZC1wb2JyZX0NCiMgcGFycmlzaGVzIHdpdGggbmVnYXRpdmUgcG9vciBwZXJzb25zIGFyZSByZWNvZGVkIGFzICIwIiBzbyB0aGV5IHdvbid0IG1lc3MgdXAgdGhlIHNjYWxlDQojIGV2ZW4gdGhvdWdoIHRoaXMgbWVhbnMgdGhhdCB0aGVpciB0b29sdGlwcyBhcmUgZHJvcHBlZCANCg0KZ2Fwc19tYXAgPC0gcGFyciAlPiUgDQogIHJpZ2h0X2pvaW4ocGNvZGUzX3NoYXBlLCBieSA9ICJwY29kZTMiKSAlPiUgDQogIHN0X2FzX3NmKCkgJT4lIA0KICBtdXRhdGUobm90X3JlYWNoZWQgPSBpZmVsc2Uobm90X3JlYWNoZWQgPCAwLjEsIDAsIG5vdF9yZWFjaGVkKSkgJT4lIA0KICBtdXRhdGUobm90X3JlYWNoZWQgPSByb3VuZChub3RfcmVhY2hlZCwgZGlnaXRzID0gMCkpICU+JQ0KICBtdXRhdGVfYXQodmFycyhwZXJjZW50X3BvYnJlLCBwZXJjZW50X3VyYmFuYSksIH4ocm91bmQoLiwgZGlnaXRzID0gMikpKSAlPiUgDQogIGdncGxvdCgpICsNCiAgZ2VvbV9zZihhZXMoZmlsbCA9IG5vdF9yZWFjaGVkLA0KICAgICAgICAgICAgICB0ZXh0ID0gcGFzdGUwKHBhcnJvcXVpYSwiLCIsICJcbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVuaWNpcGlvLCAiLCIsICJcbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBlc3RhZG8sICJcbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vdCByZWFjaGVkOiAiLCBub3RfcmVhY2hlZCwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJvcmcgY291bnQ6ICIsIG9yZ19jb3VudCwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJwb3ZlcnR5IGluY2lkZW5jZTogIiwgcGVyY2VudF9wb2JyZSwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50IHVyYmFuOiAiLCBwZXJjZW50X3VyYmFuYSkpLA0KICAgICAgICAgIHNpemUgPSAwLjEpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Mob3B0aW9uID0gInR1cmJvIiwgdHJhbnMgPSAibG9nMTAiKSArDQogIHRoZW1lX3ZvaWQoKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSArDQogIGxhYnMoZmlsbCA9ICJQb29yIHBlcnNvbnMgXG5ub3QgcmVhY2hlZCIpICsNCiAgZ2d0aXRsZSgiTWFwIG9mIHBhcnJpc2hlcyBieSBnYXBzIGluIHBvcHVsYXRpb24gcmVhY2hlZCIpDQoNCiMgc28gYXJlIHlvdSBzYXlpbmcgdGhhdCBpZiBJIGNoYW5nZSB0aGUgZmlsbCB0byB2aXJpZGlzIGluIHRoZSBsYXRlciBwbG90LCBJIGNhbiB1c2UgaG92ZXJvbiA9IGZpbGw/DQojIG5vIHlvdSBjYW4ndC4gDQpnZ3Bsb3RseShnYXBzX21hcCwgdG9vbHRpcCA9IGMoInRleHQiKSkgJT4lDQogIGxheW91dChzaG93bGVnZW5kID0gVFJVRSwgbGVnZW5kID0gbGlzdChmb250ID0gbGlzdChzaXplID0gNikpKSAlPiUgDQogIHN0eWxlKGhvdmVyb24gPSAiZmlsbCIpICU+JSANCiAgbGF5b3V0KHRpdGxlID0gbGlzdCh0ZXh0ID0gcGFzdGUwKCJNYXAgb2YgcGFycmlzaGVzIGJ5IG51bWJlciBwb29yIHBlcnNvbnMgbm90IHJlYWNoZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxzdXA+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb3VzZSBvdmVyIGZvciBkZXRhaWxzOyBkcmFnIGFuZCBjbGljayB0byBzZWxlY3QgYW5kIHpvb207IGRvdWJsZS1jbGljayBsZWdlbmQgc2VsZWN0L2Rlc2VsZWN0IiwiPC9zdXA+IikpKQ0KDQpgYGANCg0KTmF0aW9ud2lkZSwgKipgciBmb3JtYXQocm91bmQoc3VtKHBhcnIwJG5vdF9yZWFjaGVkKSwgZGlnaXRzID0gMCksIGJpZy5tYXJrID0gIiwiKWAqKiBwb29yIHBlcnNvbnMgaGF2ZSBub3QgYmVlbiBjb3ZlcmVkIGJ5IHJlc3BvbnNlIGFjdGl2aXRpZXMgLS0gdGhpcyBtZWFucyB0aGF0ICoqYHIgcm91bmQoc3VtKHBhcnIwJG5vdF9yZWFjaGVkKSAvIHN1bShwYXJyMCRwb2JfcG9icmUpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogYWxsIHRoZSBwb29yIHBlcnNvbnMgaW4gdGhlIGNvdW50cnkgaGF2ZSB5ZXQgdG8gYmUgcmVhY2hlZC4gSXQgaXMgdGhpcyBwb3B1bGF0aW9uIGFuZCBpdHMgZGlzdHJpYnV0aW9uIGFuZCB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIGl0cyBzdWItZ3JvdXBzIHRoYXQgaXMgdGhlIG1haW4gY29uY2VybiBvZiB0aGlzIGFuYWx5c2lzLiANCg0KPGJyPg0KDQojIyMgMmIuIEdyb3VwaW5nIHBhcnJpc2hlcyBieSBjb3ZlcmFnZQ0KDQpBcyBhIHN0YXJ0aW5nIHBvaW50LCBhbGwgYHIgbnJvdyhwYXJyKWAgcGFycmlzaGVzIChhZG1pbiBsZXZlbCAzKSBoYXZlIGJlZW4gc3BsaXQgaW50byB0aHJlZSBncm91cHMgLS0gX292ZXJfLCB3aGVyZSB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBiZW5lZmljaWFyaWVzIHJlYWNoZWQgZXhjZWVkcyB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucyBpbiB0aGF0IHBhcnJpc2g7IF91bmRlcl8sIHdoZXJlIHRoZSBjb3ZlcmFnZSBpcyBsZXNzIHRoYW4gdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnM7IGFuZCBfbm8gY292ZXJhZ2VfLCBjb21wcmlzaW5nIGEgdG90YWwgb2YgYHIgbnJvdyhmaWx0ZXIocGFyciwgYmVuZWZpY2lhcmlvcyA9PSAwKSlgIHBhcnJpc2hlcywgd2hlcmUgbm8gYWN0aXZpdGllcyBoYXZlIG9jY3VycmVkLiANCg0KSG93ZXZlciwgaXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgYSB0b3RhbCBvZiAqKmByIHJvdW5kKHN1bShwYXJyMCRub3RfcmVhY2hlZCksIGRpZ2l0cyA9IDApICU+JSBmb3JtYXQoYmlnLm1hcmsgPSAiLCIpYCoqIHBvb3IgcGVyc29ucyByZXNpZGUgaW4gdGhlICoqYHIgbnJvdyhmaWx0ZXIocGFyciwgYmVuZWZpY2lhcmlvcyA9PSAwKSlgKiogcGFycmlzaGVzIHRoYXQgaGF2ZSBub3QgYmVlbiByZWFjaGVkLCB0aGlzIGlzIG9ubHkgKipgciByb3VuZChmaWx0ZXIocGFyciwgYmVuZWZpY2lhcmlvcyA9PSAwKSAlPiUge3N1bSguJHBvYl9wb2JyZSl9IC8gc3VtKHBhcnIkbm90X3JlYWNoZWQpICoxMDAsIGRpZ2l0cyA9IDApYCUqKiBvZiB0aGUgKipgciByb3VuZChzdW0ocGFyciRub3RfcmVhY2hlZCksIGRpZ2l0cyA9IDApICU+JSBmb3JtYXQoYmlnLm1hcmsgPSAiLCIpYCoqIHBvb3IgcGVyc29ucyBub3QgY292ZXJlZCBieSByZXNwb25zZSBhY3Rpdml0aWVzLiBUaGlzIGluZGljYXRlcyB0aGF0DQoNCjEuIHRoZXJlIGlzIG11Y2ggcm9vbSB0byBleHBhbmQgaW4gdGhlIHBhcnJpc2hlcyB3aGVyZSB3ZSBhcmUgYWxyZWFkeSBwcmVzZW50IGFuZCB0aGF0IA0KMi4gc3BhcmVseSBwb3B1bGF0ZWQsIHJlbW90ZSBhbmQsIGNvbnNlcXVlbnRseSwgcG9vcmVyIHBhcnJpc2hlcyBoYXZlLCBzbyBmYXIsIGJlZW4gbGVmdCBvdXQgb2YgdGhlIHJlc3BvbnNlLiANCg0KDQpgYGB7cn0NCnBhcnIgJT4lIA0KICBtdXRhdGUoY292ZXJhZ2VfdHlwZSA9IGNhc2Vfd2hlbihub3RfcmVhY2hlZCA8PSAwIH4gIm92ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RfcmVhY2hlZCA+IDAgJiBiZW5lZmljaWFyaW9zID49IDEgfiAidW5kZXIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9PSAwIH4gIm5vX2NvdmVyYWdlIikpICU+JSANCiAgZ3JvdXBfYnkoY292ZXJhZ2VfdHlwZSkgJT4lIA0KICBzdW1tYXJpc2UocGFycm9xdWlhcyA9IG4oKSwNCiAgICAgICAgICAgIGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICBub3RfcmVhY2hlZCA9IHN1bShub3RfcmVhY2hlZCksIA0KICAgICAgICAgICAgYXZnX29yZ19jb3VudCA9IG1lYW4ob3JnX2NvdW50KSwNCiAgICAgICAgICAgIHBlcmNlbnRfcG9icmUgPSByb3VuZChzdW0ocG9iX3BvYnJlKSAvIHN1bShwb2JsYWNpb25fMjAxOSkgKiAxMDAsIGRpZ2l0cyA9IDEpLA0KICAgICAgICAgICAgcGVyY2VudF91cmJhbmEgPSByb3VuZChzdW0ocG9iX3VyYmFuYSkgL3N1bShwb2JsYWNpb25fMjAxOSkgKiAxMDAsIGRpZ2l0cyA9IDEpLA0KICAgICAgICAgICAgcGVyY2VudF93b19zYWZlX3dhdGVyID0gcm91bmQoc3VtKHBvYl9zaW5fYWd1YV9zZWd1cmEpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSAqIDEwMCwgZGlnaXRzID0gMSksDQogICAgICAgICAgICBwZXJjZW50X3dvX2ltcHJvdmVkX3Nhbml0YXRpb24gPSByb3VuZChzdW0ocG9iX3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbykvDQogICAgICAgICAgICAgIHN1bShwb2JsYWNpb25fMjAxOSkgICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgICAgIHBlcmNlbnRfaWxsaXRlcmF0ZSA9IHJvdW5kKHN1bShwb2JfYW5hbGZhYmV0bykgLyBzdW0ocG9ibGFjaW9uXzIwMTkpICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgICAgIGF2Z19zZWN0b3JfY291bnQgPSBtZWFuKHNlY3Rvcl9jb3VudCkpICU+JSANCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtY292ZXJhZ2VfdHlwZSwgbmFtZXNfdG8gPSAidmFyaWFibGUiKSAlPiUgDQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBjb3ZlcmFnZV90eXBlLCB2YWx1ZXNfZnJvbSA9IHZhbHVlKSAlPiUgDQogIA0KICByZWxvY2F0ZShub19jb3ZlcmFnZSwgLmFmdGVyID0gdW5kZXIpICU+JSANCiAgcGFuZGVyKGJpZy5tYXJrID0gIiwiLCBjYXB0aW9uID0gIlBhcnJpc2hlcyBjaGFyYWN0ZXJpc3RpY3MgYnkgY292ZXJhZ2UgdHlwZSIsIHN0eWxlID0gInJtYXJrZG93biIpDQoNCmBgYA0KDQpXZSBub3RlIHRoYXQgdGhlICoqYHIgbnJvdyhwYXJyW3BhcnIkbm90X3JlYWNoZWQgPD0gMCxdKWAqKiBwYXJyaXNoZXMgaW4gdGhlIF9vdmVyXyBjYXRlZ29yeSBhcmUgbXVjaCBsZXNzIHBvb3IgYW5kIG11Y2ggbW9yZSB1cmJhbiBkZXNwaXRlIGhhdmluZyAqKmByIHJvdW5kKGZpbHRlcihwYXJyLCBub3RfcmVhY2hlZCA8PSAwKSAlPiUge3N1bSguJGJlbmVmaWNpYXJpb3MpfSAvIHN1bShwYXJyJGJlbmVmaWNpYXJpb3MpICogMTAwLCBkaWdpdHMgPSAwKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJpZXMuIFRoZXNlIHBhcnJpc2hlcyBhcmUgc2hvd24gaW4gdGhlIHRhYmxlIGJlbG93LiBBbmQsIGFzIGNhbiBiZSBzZWVuIGZyb20gKipgbm90X3JlYWNoZWRgKiosIHRoZSBudW1iZXIgYmVuZWZpY2lhcmllcyBpbiB0aGUgX292ZXJfIGNhdGVnb3J5IGhhcyBncmVhdGx5IGV4Y2VlZGVkIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zLiANCg0KPGJyPg0KDQojIyMgMmMuIFRvcCBwYXJyaXNoZXMgaW4gdGVybXMgb2YgY292ZXJhZ2UNCg0KVGhlICoqYHIgbnJvdyhwYXJyW3BhcnIkbm90X3JlYWNoZWQgPD0gMCxdKWAqKiBwYXJyaXNoZXMgYmVsb3cgKGZyb20gdGhlIF9vdmVyXyBjYXRlZ29yeSkgd2lsbCBsYXJnZWx5IGJlIGV4Y2x1ZGVkIGluIHRoZSByZW1haW5kZXIgb2YgdGhpcyByZXBvcnQgYXMgaXQgaXMgY2xlYXIgdGhhdCBubyBmdXJ0aGVyIHJlc291cmNlcyBzaG91bGQgYmUgYWxsb2NhdGVkIHRvIHRoZW06IA0KDQpgYGB7cn0NCnBhcnIgJT4lIA0KICBtdXRhdGUoY292ZXJhZ2VfdHlwZSA9IGNhc2Vfd2hlbihub3RfcmVhY2hlZCA8PSAwIH4gIm92ZXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3RfcmVhY2hlZCA+IDAgJiBiZW5lZmljaWFyaW9zID49IDEgfiAidW5kZXIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuZWZpY2lhcmlvcyA9PSAwIH4gIm5vdF9yZWFjaGVkIikpICU+JSAgDQogIGZpbHRlcihjb3ZlcmFnZV90eXBlID09ICJvdmVyIikgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBtdW5pY2lwaW8sIGVzdGFkbywgcGFycm9xdWlhLCBiZW5lZmljaWFyaW9zLCBwb2JfcG9icmUpICU+JQ0KICBtdXRhdGUoY292ZXJhZ2VfcGVyY2VudCA9IGJlbmVmaWNpYXJpb3MgLyBwb2JfcG9icmUgKiAxMDApICU+JSANCiAgYXJyYW5nZShkZXNjKGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIHBhbmRlcihiaWcubWFyayA9ICIsIiwgY2FwdGlvbiA9ICJUb3AgMTEgcGFycmlzaGVzIGJ5IGNvdmVyYWdlIiwgc3R5bGUgPSAicm1hcmtkb3duIikNCg0KYGBgDQoNCkFzIGEgbm90ZSwgaXQgaXMgbGlrZWx5IHRoYXQgcGFydG5lcnMgaGF2ZSByZXBvcnRlZCBhY3Rpdml0aWVzIHdoaWNoIG9jY3VycmVkIGluIG90aGVyIHBhcnRzIG9mIHRoZSBjYXBpdGFsIGluIEFsdGFncmFjaWEsIGFzIHRoZSB0b3RhbCBudW1iZXIgb2YgYmVuZWZpZmljYXJpZXMgcmVhY2hlZCBpbiB0aGUgd2hvbGUgb2YgRGlzdHJpdG8gQ2FwaXRhbCBpcyBvbmx5IGByIGZpbHRlcihwYXJyLCBtdW5pY2lwaW8gPT0gIkxJQkVSVEFET1IiKSAlPiUge3N1bSguJGJlbmVmaWNpYXJpb3MpfSAlPiUgZm9ybWF0KGJpZy5tYXJrID0gIiwiKWAuIEl0IGlzIG5lY2Vzc2FyeSB0byBjaGVjayBiYWNrIHdpdGggcGFydG5lcnMgYWJvdXQgdGhpczsgbmV2ZXJ0aGVsZXNzLCB0aGlzIGlzIHRoZSBpbmZvcm1hdGlvbiB3ZSBoYXZlIG9uIGhhbmQuIA0KDQoNCjxicj4NCg0KIyMgMy4gR2VvZ3JhcGhpY2FsIGFuYWx5c2lzIG9mIEdhcHMNCg0KIyMjIDNhLiBCYXJwbG90IG9mIGNvdmVyYWdlIGFuZCBnYXBzIGJ5IHN0YXRlDQoNCmBgYHtyIHBhcnIwLXN0YXRlLVBMT1QsIGZpZy5oZWlnaHQ9NX0NCiMgcmVmIGZvciBwcmludGluZyBzdGF0ZV9vcmQuIEknbSByZWFsbHkgbm90IHN1cmUgaG93IHRvIGV4dHJhY3QgYWxsIHRoZSB2YXJpYWJsZXMgYXMgYSBsaXN0DQojIHBhcnIwICU+JSANCiMgICBncm91cF9ieShlc3RhZG8pICU+JSANCiMgICBzdW1tYXJpc2Uobm90X3JlYWNoZWQgPSBzdW0obm90X3JlYWNoZWQpKSAlPiUgDQojICAgYXJyYW5nZShkZXNjKG5vdF9yZWFjaGVkKSkgJT4lIA0KIyAgIHNlbGVjdChlc3RhZG8pICU+JSBhcy5saXN0KGFzLmRhdGEuZnJhbWUodCguKSkpDQoNCnN0YXRlX29yZCA8LSBjKCJaVUxJQSIsICJMQVJBIiwgIkNBUkFCT0JPIiwgIk1JUkFOREEiLCAiQU5aT0FURUdVSSIsICJBUkFHVUEiLCAiQk9MSVZBUiIsDQogICAgICAgICAgICAgICAiUE9SVFVHVUVTQSIsICJTVUNSRSIsICJHVUFSSUNPIiwgIkZBTENPTiIsICJNT05BR0FTIiwgIkJBUklOQVMiLCAiTUVSSURBIiwNCiAgICAgICAgICAgICAgICJUQUNISVJBIiwgIlRSVUpJTExPIiwgIllBUkFDVVkiLCAiQVBVUkUiLCAiRElTVFJJVE8gQ0FQSVRBTCIsICJOVUVWQSBFU1BBUlRBIiwNCiAgICAgICAgICAgICAgICJDT0pFREVTIiwgIlZBUkdBUyIsICJERUxUQSBBTUFDVVJPIiwgIkFNQVpPTkFTIikNCiAgDQpzdGFja190ZXh0IDwtIHBhcnIwICU+JSANCiAgZ3JvdXBfYnkoZXN0YWRvKSAlPiUgDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgICAgdG90YWwgPSBzdW0ocG9iX3BvYnJlKSkgJT4lIA0KICBtdXRhdGUocGVyY2VudF9yZWFjaGVkID0gcm91bmQoYmVuZWZpY2lhcmlvcyAvIHRvdGFsICogMTAwLCBkaWdpdHMgPSAyKSkgJT4lIA0KICBhcnJhbmdlKGRlc2ModG90YWwpKSANCg0Kc3RhdGVfc3RhY2sgPC0gcGFycjAgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBiZW5lZmljaWFyaW9zLCBub3RfcmVhY2hlZCkgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JQ0KICBzdW1tYXJpc2UoYmVuZWZpY2lhcmlvcyA9IHJvdW5kKHN1bShiZW5lZmljaWFyaW9zKSwgZGlnaXRzID0gMCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSByb3VuZChzdW0obm90X3JlYWNoZWQpLCBkaWdpdHMgPSAwKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoYyhiZW5lZmljaWFyaW9zLCBub3RfcmVhY2hlZCksDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJwb2JfdHlwZSIsIHZhbHVlc190byA9ICJ0b3RhbCIpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IGVzdGFkbywgeSA9IHRvdGFsKSkgKw0KICBnZW9tX2NvbChhZXMoZmlsbCA9IHBvYl90eXBlKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWwgPSBjb21tYSkgKw0KICBzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHN0YXRlX29yZCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjb3JhbCIsICJyb3lhbGJsdWUiKSkgKw0KICBnZW9tX3RleHQoZGF0YSA9IHN0YWNrX3RleHQsIGFlcyh5ID0gMjAwMDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gcGVyY2VudF9yZWFjaGVkKSwgDQogICAgICAgICAgICBzaXplID0gMiwgZm9udGZhY2UgPSAiYm9sZCIsIGNvbG91ciA9ICJ3aGl0ZSIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZSA9IDYuNSksDQogICAgICAgIGF4aXMudGV4dC55ICA9IGVsZW1lbnRfdGV4dChzaXplID0gNSksDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSksDQogICAgICAgIHBsb3QudGl0bGUgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSArDQogIHhsYWIoIiIpICsgeWxhYigiTnVtYmVyIG9mIHBvb3IgcGVyc29ucyIpICsgDQogIGxhYnMoZmlsbCA9ICIiLA0KICAgICAgIHRpdGxlID0gIkJhcnBsb3Qgb2YgcG9vciBwZXJzb25zIGJ5IHN0YXRlIGJ5IHJlYWNoZWQvbm90IHJlYWNoZWQiKQ0KDQpnZ3Bsb3RseShzdGF0ZV9zdGFjaykgJT4lIA0KICBsYXlvdXQobGVnZW5kID0gbGlzdChmb250ID0gbGlzdChzaXplID0gNykpKSAlPiUgDQogIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IEZBTFNFKSAlPiUgDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgNCiAgICAiQmFycGxvdCBvZiBwb29yIHBlcnNvbnMgYnkgc3RhdGUgYnkgcmVhY2hlZC9ub3QgcmVhY2hlZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPHN1cD4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1vdXNlIG92ZXIgZm9yIGRldGFpbHMiLCI8L3N1cD4iKSkpDQoNCmBgYA0KDQoqKmByIHJvdW5kKGZpbHRlcihwYXJyLCBlc3RhZG8gJWluJSBjKCJESVNUUklUTyBDQVBJVEFMIiwgIk1JUkFOREEiLCAiWlVMSUEiLCAiVEFDSElSQSIsICJCT0xJVkFSIikpICU+JSB7c3VtKC4kYmVuZWZpY2lhcmlvcyl9IC8gc3VtKHBhcnIkYmVuZWZpY2lhcmlvcykgKiAxMDAsIGRpZ2l0cyA9IDApYCUqKiBvZiBhbGwgYmVuZWZpY2lhcmllcyBhcmUgZnJvbSB0aGUgc3RhdGVzIG9mIERpc3RyaXRvIENhcGl0YWwsIE1pcmFuZGEsIFRhY2hpcmEsIEJvbGl2YXIgYW5kIFp1bGlhLCBsYXJnZWx5IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGxvY2F0aW9ucyBvZiBVTklDRUYgb2ZmaWNlcy4gVGhlc2Ugc3RhdGVzLCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBEZWx0YSBBbWFjdXJvLCBhcmUgYWxzbyB3aGVyZSB0aGUgaGlnaGVzdCBwZXJjZW50YWdlcyBvZiBwb29yIHBlcnNvbnMgaGF2ZSBiZWVuIHJlYWNoZWQsIGluZGljYXRpbmcgc29tZSBvdmVyYWxsb2NhdGlvbiBoYXMgb2NjdXJyZWQuIA0KDQpDYXJhYm9ibyBoYXMgdGhlIGxvd2VzdCBwZXJjZW50YWdlIG9mIGl0cyBwb29yIHBvcHVsYXRpb24gY292ZXJlZC4gT24gYXZlcmFnZSwgYWZ0ZXIgdGhlIGV4Y2x1c2lvbiBvZiB0aGUgdG9wIGByIG5yb3cocGFycltwYXJyJG5vdF9yZWFjaGVkIDw9IDAsXSlgIHBhcnJpc2hlcywgKipgciByb3VuZChzdW0ocGFyciRiZW5lZmljaWFyaW9zKSAvIHN1bShwYXJyJHBvYl9wb2JyZSkgKiAxMDAsIGRpZ2l0cyA9IDEpYCUqKiBvZiBwb29yIHBlcnNvbnMgaGF2ZSBiZWVuIHJlYWNoZWQgY291bnRyeXdpZGUuIA0KDQpXaGlsc3QgdGhlcmUgYXJlIG1hbnkgcG9vciBwZXJzb25zIHlldCB0byBiZSByZWFjaGVkIGluIHN0YXRlcyB3aGVyZSB3ZSBoYXZlIHJlbGF0aXZlbHkgaGlnaCBjb3ZlcmFnZSwgdGhlcmUgaXMgYSBuZWVkIHRvIGVuc3VyZSB0aGF0IG91ciBvcGVyYXRpb25hbCBmb290cHJpbnQgYW5kIHRoZSBjb25zZXF1ZW50IHJlc291cmNlcyBhbGxvY2F0ZWQgYXJlIGVxdWl0YWJsZSAtLSB0aGUgY3Jpc2lzIGluIFZlbmV6dWVsYSBpcyBuYXRpb253aWRlLCBhbmQgdW5saWtlIGFuIGVhcnRocXVha2Ugb3IgYSB0eXBob29uIHdoZXJlIHRoZXJlIGlzIGFuIGVwaWNlbnRyZSBvciBhIHN0b3JtcGF0aCwgdGhlcmUgaXMgbm8gcHJvZ3JhbW1hdGljIHJhdGlvbmFsZSB0byBvbmx5IGZvY3VzIG9uIGEgZmV3IGFyZWFzLiANCg0KTGV0IHVzIG5vdyBtb3ZlIGRvd24gdG8gYSBsb3dlciBsZXZlbCBvZiBncmFudWxhcml0eSBhcyBzdGF0ZS1sZXZlbCBhbmFseXNpcyBpcyBzdGlsbCB0b28gc3VwZXJmaWNpYWwuIFBhcnJpc2hlcyB3aWxsIGJlIHRoZSBtYWluIGFkbWluaXN0cmF0aXZlIHVuaXQgb2YgcmVmZXJlbmNlIGluIHRoaXMgYW5hbHlzaXMuIFVubGlrZSBpbiB0aGUgNVcgY2xlYW5pbmcgYW5kIHJlcG9ydGluZyBkb2N1bWVudCwgd2hlcmUgd2UgZm9jdXNlZCBvbiBtdW5pY2lwYWxpdGllcyB0byBkaXNwbGF5IGFjaGlldmVtZW50cyBmb3IgZXh0ZXJuYWwgYXVkaWVuY2VzLCBncmVhdGVyIHByZWNpc2lvbiBpcyBuZWVkZWQgZm9yIGEgY292ZXJhZ2UgYW5kIGdhcHMgYW5hbHlzaXMuDQoNCjxicj4NCg0KIyMjIDNiLiBTY2F0dGVycGxvdCBvZiBnYXBzIGJ5IHBhcnJpc2ggDQoNCkZyb20gdGhlIHNjYXR0ZXJwbG90IGJlbG93IC0tIHdoZXJlIGVhY2ggcG9pbnQgaXMgYSBwYXJyaXNoIC0tIHdlIHNlZSB0aGF0IHRoZXJlIGlzIGdyZWF0IHZhcmlhdGlvbiBib3RoIGluIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkIChzaXplIGFuZCB4LWF4aXMpIGFzIHdlbGwgYXMgaG93IGNvbmNlbnRyYXRlZCB0aGV5IGFyZSBpbiBhIGdpdmVuIHBhcnJpc2ggKHktYXhpcywgcG92ZXJ0eSBpbmNpZGVuY2UpOyBib3RoIHRoZXNlIGZhY3RvcnMgd2VpZ2ggaGVhdmlseSBpbiBwcm9ncmFtbWluZyBzdHJhdGVnaWVzIGFzIHdlbGwgYXMgaW4gdGhlIGVhc2Ugb2YgYmVuZWZpY2lhcnkgc2VsZWN0aW9uLiAgDQoNClRoZSBncmVhdGVzdCBudW1iZXJzIG9mIG5vdCByZWFjaGVkIGFyZSBmb3VuZCBpbiBwYXJyaXNoZXMgYmV0d2VlbiB0aGUgcmFuZ2VzIG9mIF9wb29yIHBlcnNvbnM6XyAxMCwwMDAtMTAwLDAwMCBhbmQgX3BvdmVydHkgaW5jaWRlbmNlOl8gMC4yNS0wLjUwIChtYXJrZWQgYnkgdGhlIHllbGxvdyBib3gpOyBob3dldmVyLCB0aGVzZSBwYXJyaXNoZXMgYWxzbyBoYXZlIGEgbXVjaCBoaWdoZXIgdGhhbiBhdmVyYWdlIG51bWJlciBvZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgKG1vcmUgcmVkKS4gVGhpcyBtZWFucyB0aGF0IG9wZXJhdGlvbmFsIGJhcnJpZXJzIGFyZSBtdWNoIGxvd2VyIGluIGFjY2Vzc2luZyB0aGVzZSBwb3B1bGF0aW9ucyB0aGFuIHRoZSBwYXJyaXNoZXMgaW4gbGlnaHQgYmx1ZSBmb3VuZCBpbiB0aGUgbWlkZGxlIG9mIHRoZSBwbG90Lg0KDQpgYGB7ciBwYXJycGxvdC1QTE9UTFksIGZpZy5oZWlnaHQ9NX0NCg0KcGFycnBsb3QgPC0gcGFycjAgJT4lIA0KICBtdXRhdGVfYXQodmFycyhwb2JfcG9icmUsIG5vdF9yZWFjaGVkLCBvcmdfY291bnQpLCB+KHJvdW5kKC4pKSkgJT4lIA0KICBtdXRhdGUocGVyY2VudF9wb2JyZSA9IHJvdW5kKHBlcmNlbnRfcG9icmUsIGRpZ2l0cyA9IDIpKSU+JSANCiAgZ2dwbG90KGFlcyh4ID0gbm90X3JlYWNoZWQsIHkgPSBwZXJjZW50X3BvYnJlLCANCiAgICAgICAgICAgICBjb2xvdXIgPSBvcmdfY291bnQsIA0KICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAocGFycm9xdWlhLCAiLCAiLCBlc3RhZG8pKSkgKw0KICAgZ2VvbV9yZWN0KGFlcyh4bWluID0gMTAwMDAsIHhtYXggPSAxMDAwMDAsIHltaW4gPSAwLjI1LCB5bWF4ID0gMC41MCksDQogICAgICAgICAgICBmaWxsID0gInRyYW5zcGFyZW50IiwgY29sb3VyID0gImdvbGQiLCBzaXplID0gMC4yKSArDQogIGdlb21faml0dGVyKGFlcyhzaXplID0gbm90X3JlYWNoZWQpLCBhbHBoYSA9IDAuNzUpICsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bigNCiAgICBjb2xvdXJzID0gYygiY29ybmZsb3dlcmJsdWUiLCAidG9tYXRvIiwgImZpcmVicmljayIpKSArDQogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIGxhYmVscyA9IGNvbW1hKSArIA0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMywgNSkpICsNCiAgeGxhYigiTm90IGNvdmVyZWQgcG9vciIpICsgeWxhYigiUG92ZXJ0eSBpbmNpZGVuY2UiKSArDQogIGxhYnMoY29sb3VyID0gIk51bWJlciBvZiBcbm9yZ2FuaXNhdGlvbnMiLCANCiAgICAgICB0aXRsZSA9ICJTY2F0dGVycGxvdCBvZiBwYXJyaXNoZXMgYnkgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkIGFuZCBwb3ZlcnR5IGluY2lkZW5jZSIpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSksDQogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDguNSkpIA0KICANCg0KZ2dwbG90bHkocGFycnBsb3QsIHRvb2x0aXAgPSBjKCJ5IiwgIngiLCAic2l6ZSIsICJ0ZXh0IiwgImNvbG91ciIpKSAlPiUgDQogICAgICAgICAgIGxheW91dChzaG93bGVnZW5kID0gVFJVRSwgbGVnZW5kID0gbGlzdChmb250ID0gbGlzdChzaXplID0gNykpKSAlPiUNCiAgICAgICAgICAgY29uZmlnKGRpc3BsYXlNb2RlQmFyID0gRkFMU0UpICU+JSANCiAgbGF5b3V0KHRpdGxlID0gbGlzdCh0ZXh0ID0gcGFzdGUwKA0KICAgICJTY2F0dGVycGxvdCBvZiBwYXJyaXNoZXMgYnkgbnVtYmVyIHBvb3IgcGVyc29ucyBub3QgcmVhY2hlZCBhbmQgcG92ZXJ0eSBpbmNpZGVuY2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxzdXA+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzaXplOiBudW1iZXIgb2YgcG9vciBwZXJzb25zIG5vdCByZWFjaGVkOyBjb2xvdXI6IG51bWJlciBvZiBvcmdhbmlzYXRpb25zIHByZXNlbnQ7IGRyYWcgYW5kIGNsaWNrIHRvIHNlbGVjdCBhbmQgem9vbSIsIjwvc3VwPiIpKSkNCg0KYGBgDQoNCkZvciBhZ2VuY2llcyB0cnVseSB1bmFibGUgdG8gZXhwYW5kIG91dHNpZGUgdGhlaXIgY3VycmVudCBmb290cHJpbnRzLCB0aGVyZSBhcmUgc3RpbGwgbWFueSBiZW5lZmljaWFyaWVzIHdobyBhcmUgbm90IGNvdmVyZWQgb3IgLS0gYXMgd2Ugd2lsbCBkaXNjdXNzIGluIHRoZSBuZXh0IHBhcnQgLS0gaGF2ZSBvbmx5IGJlZW4gcmVhY2hlZCB3aXRoIHRoZSBpbnRlcnZlbnRpb25zIG9mIG9uZSBzZWN0b3IuDQoNCjxicj4gDQoNCiMjIDQuIE11bHRpLXNlY3RvciBwcm9ncmFtbWluZw0KDQpIdW1hbml0YXJpYW4gZW1lcmdlbmNpZXMgYXJlIG11bHRpZGltZW5zaW9uYWwgYW5kIGRvIG5vdCBhZmZlY3Qgb25seSBvbmUgYXNwZWN0IG9mIHRoZSBsaXZlcyBvZiBhZmZlY3RlZCBwZXJzb25zLiBQaGVub21lbmEgc3VjaCBhcyBkaXNwbGFjZW1lbnQgb3IgZm9vZCBpbnNlY3VyaXR5IHJlc3VsdCBmcm9tIHRoZSBjb21wbGV4IGludGVycGxheSBvZiBudW1lcm91cyB1bmRlcmx5aW5nIGZhY3RvcnMgYW5kIHRoZSBzaG9ja3MgYW5kIHN0cmVzc2VzIG9mIHRoZSBoYXphcmQuIFRoZSByZXNwb25zZSB0byB0aGlzLCBtdWx0aS1zZWN0b3Igb3IgaW50ZWdyYXRlZCBwcm9ncmFtbWluZywgY29uc2lzdHMgb2YgaW1wbGVtZW50aW5nIGxheWVycyBvZiBpbmRpdmlkdWFsLCBob3VzZWhvbGQgYW5kIGNvbW11bml0eS1sZXZlbCBpbnRlcnZlbnRpb25zIHRvIGNvbXByZWhlbnNpdmVseSBtZWV0IHRoZSBuZWVkcyBvZiB0aGUgdGFyZ2V0IHBvcHVsYXRpb24uIEl0IGlzIG9mdGVuIGhlbGQgdXAgYXMgYSBnb2xkIHN0YW5kYXJkIGluIHN0cmF0ZWd5IGRvY3VtZW50cyBhbmQgaHVtYW5pdGFyaWFuIHN0YW5kYXJkcywgYnV0IHJhcmVseSBhY2hpZXZlZCBpbiBwcmFjdGljZS4gDQoNCiMjIyA0YS4gU3VtbWFyeSB0YWJsZSBvZiBtdWx0aS1zZWN0b3IgY292ZXJhZ2UgDQoNCkhvd2V2ZXIsIGp1c3QgYmVjYXVzZSB0d28gQ2x1c3RlcnMgb3BlcmF0ZSBpbiB0aGUgc2FtZSBhcmVhIGRvIG5vdCBtZWFuIHRoZWlyIGJlbmVmaWNpYXJpZXMgY29pbmNpZGUuIEFzIGFuIGVzdGltYXRlLCB3ZSBjYWxjdWxhdGVkIGEgdGhlb3JldGljYWwgbWF4aW11bSBudW1iZXIgb2YgbXVsdGktc2VjdG9yIGJlbmVmaWNpYXJpZXMgcGVyIHBhcnJpc2gsIGV4cHJlc3NlZCBiZWxvdyBhcyBgbXVsdGlfc2VjdG9yX2JlbmAgKGV4YWN0IGNhbGN1bGF0aW9uIGFuZCBleHBsYW5hdGlvbiBpbiB0aGUgY29kZSBjaHVuayBiZWxvdykuIFBhcnJpc2hlcyBoYXZlIHRoZW4gYmVlbiBzcGxpdCBpbnRvIGdyb3VwcyBiYXNlZCBvbiB0aGUgbnVtYmVyIG9mIHNlY3RvcnMgcHJlc2VudCB3aXRoaW4gdGhlbToNCg0KYGBge3IgbXVsdGktc2VjdG9yLWJlbi1UQUJMRS1hbmQtUkVGfQ0KIyBjYWxjdWxhdGlvbiBmb3IgbXVsdGktc2VjdG9yIGJlbmVmaWNpYXJpZXMuIA0KIyBCYXNpY2FsbHksIGJlbmVmaWNpYXJpZXMgcGVyIHBhcnJpc2ggYXJlIGFnZ3JlZ2F0ZWQgaW50byANCiMgc2VjdG9yIHN1YnRvdGFscyBhbmQgYSBiZW5lZmljaWFyeSBmcmVxdWVuY3kgdG90YWwuICANCiMgVGhlIG1heGltdW0gdmFsdWUgb2YgdGhlIHNlY3RvciBzdWJ0b3RhbHMgaXMgY29tcGFyZWQgYWdhaW5zdCB0aGUgYmVuZWZpY2lhcnkgZnJlcXVlbmN5IHRvdGFsLCANCiMgaWYgdGhlIG1heGltdW0gdmFsdWUgaXMgZXF1YWwgdG8gdGhlIGZyZXF1ZW5jeSB0b3RhbCwgdGhlbiB0aGVyZSBpcyBvbmx5IG9uZSBzZWN0b3IsDQojIGlmIHRoZSBtYXhpbXVtIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgZnJlcXVlbmN5IHRvdGFsLCANCiMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIChvciB0aGUgc3VtIG9mIGFsbCBvdGhlciBzZWN0b3Igc3VidG90YWxzKSANCiMgYmVjb21lcyB0aGUgdGhlb3JldGljYWwgbWF4aW11bSBudW1iZXIgb2YgbXVsdGlzZWN0b3IgYmVuZWZpY2lhcmllcy4NCg0KIyBQZXJmb3JtaW5nIHRoaXMgY2FsY3VsYXRpb24gYXQgYWRtaW4gbGV2ZWwgMyBtYWtlcyBzZW5zZSBhcyBhIHBhcnJpc2ggaXMgc21hbGwgZW5vdWdoDQojIHRoYXQgdGhlcmUgaXQgaXMgcmVhbGlzdGljIHRvIGFzc3VtZSB0aGF0IG92ZXJsYXBzIGluIGJlbmVmaWNpYXJpZXMgYmV0d2VlbiBzZWN0b3JzIGV4aXN0IC0tDQojIGkuZS4gdGhhdCBmZW1hbGVzIHVuZGVyIDE4IGluIGEgcGFycmlzaCB3aG8gYXJlIGJlbmVmaWNpYXJpZXMgb2YgbnV0cml0aW9uIA0KIyBhbmQgZmVtYWxlcyB1bmRlciAxOCBpbiB0aGF0IHNhbWUgcGFycmlzaCB3aG8gYXJlIGJlbmVmaWNpYXJpZXMgb2YgV0FTSCBhcmUgdGhlIHNhbWUgcGVvcGxlLiANCg0KIyBBbHRob3VnaCBJIGRvIGZlZWwgdGhpcyBjYWxjdWxhdGlvbiB0byBiZSB2ZXJ5IGNoYXJpdGFibGUgDQojIFdlIGNhbid0IHJlYWxseSBkbyBtdWNoIG1vcmUgdW5sZXNzIHRoZXJlIGlzIGEgYmVuZWZpY2lhcnkgcmVnaXN0ZXIuIA0KIyBUaGUgcmVhbCBudW1iZXIgb2YgbXVsdGlzZWN0b3IgYmVuZWZpY2lhcmllcyBpcyBsaWtlbHkgTVVDSCBMT1dFUiANCiMgYnV0IHRoYXQgY2FuIG9ubHkgYmUgdmVyaWZpZWQgdGhyb3VnaCBzYW1wbGVkIGxhcmdlLXNjYWxlIHBvc3QtZGlzdHJpYnV0aW9uL3Bvc3QtaW50ZXJ2ZW50aW9uIG1vbml0b3JpbmcsDQojIHdoaWNoIGlzIGV4dHJlbWVseSByYXJlLiANCiMgSSBhY3R1YWxseSBjb3VsZCBoYXZlIHJhaXNlZCB0aGlzIHdpdGggdGhlIHRoaXJkLXBhcnR5IG1vbml0b3JzIHRoYXQgVU5JQ0VGLCANCiMgc28gaXQncyBhbiBvdmVyc2lnaHQgb24gbXkgcGFydCBhcyB3ZWxsLg0KDQogYWN0X2JlbiAlPiUNCiAgIyB2YWNjaW5hdGlvbiBmaWx0ZXJlZCBvdXQgIA0KICAgZmlsdGVyKGNhdGVnb3JpYWRlYWN0aXZpZGFkICE9ICJWYWN1bmFjaW9uIikgJT4lDQogICAgICAgICAgICAgICAgIGdyb3VwX2J5KHViaWNhY2lvbiwgc2VjdG9yLCBwY29kZTMpICU+JSANCiAgICAgICAgICAgICAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlY3RvciwgdmFsdWVzX2Zyb20gPSBiZW5lZmljaWFyaW9zKSAlPiUgDQogICAgICAgICAgICAgICAgIHJlcGxhY2VfbmEobGlzdChOdXRyaWNpb24gPSAwLCBFZHVjYWNpb24gPSAwLCBXQVNIID0gMCwgU2FsdWQgPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2VndXJpZGFkX0FsaW1lbnRhcmlhID0gMCwgUHJvdGVjY2lvbiA9IDApKSAlPiUNCiAgICAgICAgICAgICBncm91cF9ieShwY29kZTMsIGRlc2FncmVnYWNpb24pICU+JSANCiAgICAgICAgICAgICBzdW1tYXJpc2UobnV0cmljaW9uX2JlbiAgID0gc3VtKE51dHJpY2lvbiksDQogICAgICAgICAgICAgICAgICAgICAgIHByb3RlY2Npb25fYmVuICA9IHN1bShQcm90ZWNjaW9uKSwNCiAgICAgICAgICAgICAgICAgICAgICAgd2FzaF9iZW4gICAgICAgID0gc3VtKFdBU0gpLA0KICAgICAgICAgICAgICAgICAgICAgICBzYWx1ZF9iZW4gICAgICAgPSBzdW0oU2FsdWQpLA0KICAgICAgICAgICAgICAgICAgICAgICBlZHVjYWNpb25fYmVuICAgPSBzdW0oRWR1Y2FjaW9uKSwNCiAgICAgICAgICAgICAgICAgICAgICAgc2FfYmVuICAgICAgICAgID0gc3VtKFNlZ3VyaWRhZF9BbGltZW50YXJpYSksIC5ncm91cHMgPSAiZHJvcCIpICU+JSANCiAgICAgICAgICAgICBtdXRhdGUoYmVuX2ZyZXEgICA9IG51dHJpY2lvbl9iZW4gKyBwcm90ZWNjaW9uX2JlbiArIHdhc2hfYmVuICsgc2FsdWRfYmVuICsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVkdWNhY2lvbl9iZW4gKyBzYV9iZW4sDQogICAgICAgICAgICAgICAgICAgIGJlbl9tYXggICAgPSBwbWF4KG51dHJpY2lvbl9iZW4sIHByb3RlY2Npb25fYmVuLCB3YXNoX2JlbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX2JlbiwgZWR1Y2FjaW9uX2Jlbiwgc2FfYmVuKSwNCiAgICAgICAgICAgICAgICAgICAgbXNfYmVuX21heCA9IGlmZWxzZShiZW5fbWF4ID49IGJlbl9mcmVxIC0gYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuX2ZyZXEgLSBiZW5fbWF4LCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZW5fbWF4KSkgJT4lIA0KICAgICAgICAgICAgIGdyb3VwX2J5KHBjb2RlMykgJT4lIA0KICAgICAgICAgICAgIHN1bW1hcmlzZShudXRyaWNpb25fYmVuICA9IHN1bShudXRyaWNpb25fYmVuKSwNCiAgICAgICAgICAgICAgICAgICAgICAgcHJvdGVjY2lvbl9iZW4gPSBzdW0ocHJvdGVjY2lvbl9iZW4pLA0KICAgICAgICAgICAgICAgICAgICAgICB3YXNoX2JlbiAgICAgICA9IHN1bSh3YXNoX2JlbiksDQogICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX2JlbiAgICAgID0gc3VtKHNhbHVkX2JlbiksDQogICAgICAgICAgICAgICAgICAgICAgIGVkdWNhY2lvbl9iZW4gID0gc3VtKGVkdWNhY2lvbl9iZW4pLA0KICAgICAgICAgICAgICAgICAgICAgICBzYV9iZW4gICAgICAgICA9IHN1bShzYV9iZW4pLA0KICAgICAgICAgICAgICAgICAgICAgICBiZW5fZnJlcSAgID0gc3VtKGJlbl9mcmVxKSwNCiAgICAgICAgICAgICAgICAgICAgICAgYmVuX21heCAgICA9IHN1bShiZW5fbWF4KSwNCiAgICAgICAgICAgICAgICAgICAgICAgbXNfYmVuX21heCA9IHN1bShtc19iZW5fbWF4KSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIA0KICAgICAgICAgICAgIG11dGF0ZShzZWN0b3JfY291bnQgPSByb3dTdW1zKHNlbGVjdCguLCBlbmRzX3dpdGgoIl9iZW4iKSkgIT0gMCkpICU+JSANCiAgZ3JvdXBfYnkoc2VjdG9yX2NvdW50KSAlPiUgDQogICMgZmlsdGVyaW5nIG91dCB0aGUgcGFycmlzaGVzIHdpdGggb3ZlcnN1YnNjcmlwdGlvbiANCiAgZmlsdGVyKHBjb2RlMyAlb3V0JSBjKCJWRTAxMDEwMSIsICJWRTA3MDEwNCIsICJWRTA3MDUwMiIsICJWRTA3MDUwNiIsICJWRTA4MTQwMSIsICJWRTEwMDQwMSIsDQogICAgICAgICAgICAgICAgICAgICAgICAiVkUxNTA3MDEiLCAiVkUxNTE5MDEiLCAiVkUxNTE5MDUiLCAiVkUyMDAxMDEiLCAiVkUyMDA0MDMiKSkgJT4lIA0KICBzdW1tYXJpc2UocGFycm9xdWlhcyA9IG4oKSwNCiAgICAgICAgICAgIG11bHRpX3NlY3Rvcl9iZW4gPSBzdW0obXNfYmVuX21heCksDQogICAgICAgICAgICBvbmVfc2VjdG9yX2JlbiA9IHN1bShiZW5fZnJlcSkgLSBzdW0obXNfYmVuX21heCksIA0KICAgICAgICAgICAgYG11bHRpc2VjdG9yXyVgID0gcm91bmQoc3VtKG1zX2Jlbl9tYXgpIC8gc3VtKGJlbl9mcmVxKSAqIDEwMCwgZGlnaXRzID0gMiksDQogICAgICAgICAgICAuZ3JvdXBzID0gImRyb3AiKSAlPiUgDQogIHJlbG9jYXRlKGBtdWx0aXNlY3Rvcl8lYCwgLmFmdGVyID0gb25lX3NlY3Rvcl9iZW4pICU+JSANCiAgcGFuZGVyKHN0eWxlID0gInJtYXJrZG93biIsIGNhcHRpb24gPSAiU3VtbWFyeSBvZiBtdWx0aXNlY3RvciBjb3ZlcmFnZSIpDQoNCmBgYA0KDQpPdmVyYWxsLCB0aGUgcmVzdWx0cyBhcmUgbm90IGVuY291cmFnaW5nIC0tIG9ubHkgKipgciByb3VuZChzdW0ocGFycjAkbXNfYmVuX21heCkgLyBzdW0ocGFycjAkYmVuX2ZyZXEpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJpZXMgaGF2ZSByZWNlaXZlZCBtdWx0aS1zZWN0b3Igc3VwcG9ydC4gV2hlbiB2YWNjaW5hdGlvbnMgYXJlIGluY2x1ZGVkLCB0aGUgcGVyY2VudGFnZSBkcm9wcyB0byAqKjguNyUqKi4gQnV0IHdlIHdpbGwgZXhjbHVkZSB2YWNjaW5hdGlvbnMgZm9yIHRoaXMgYW5hbHlzaXMgYXMgdGhlaXIgZm9vdHByaW50IGlzIGRldGVybWluZWQgYnkgZ292ZXJubWVudCBwcmlvcml0aWVzLCB3aGljaCBkbyBub3QgYWxpZ24gd2l0aCB0aGUgaHVtYW5pdGFyaWFuIGltcGVyYXRpdmU7IGZ1cnRoZXJtb3JlLCB0aGUgZ292ZXJubWVudCB3YXMgbm90IGFibGUgdG8gcHJvdmlkZSB2YWNjaW5hdGlvbiByZWNvcmRzIGF0IHRoZSBwYXJyaXNoIGxldmVsLCBtYW55IHRpbWVzIGRlZmF1bHRpbmcgdG8gbXVuaWNpcGFsIG9yIHN0YXRlLWxldmVsIHJlcG9ydGluZy4gDQoNCkFzIHRoZSBsZWFkZXIgb2YgdGhlIEVkdWNhdGlvbiwgTnV0cml0aW9uLCBXQVNIIGFuZCBDaGlsZCBQcm90ZWN0aW9uIENsdXN0ZXJzLCBVTklDRUYgc3VwcG9ydGVkIGFjdGl2aXRpZXMgcmVhY2hpbmcgKipgciByb3VuZCgoZmlsdGVyKGFjdF9iZW4sIG9yZ19saWRlciA9PSAiVU5JQ0VGIikgJT4lIHtzdW0oLiRiZW5lZmljaWFyaW9zKX0pIC8gc3VtKGFjdF9iZW4kYmVuZWZpY2lhcmlvcykgKiAxMDAsIGRpZ2l0cyA9IDApYCUqKiBvZiBhbGwgYmVuZWZpY2lhcmllcy4gTWVhbmluZyB0aGF0IHRoaXMgdGhlIGxvdyBwZXJjZW50YWdlIG9mIG11bHRpLXNlY3RvciBzdXBwb3J0IGNvdWxkIGJlIHJlc29sdmVkIGFsbW9zdCBlbnRpcmVseSBieSBiZXR0ZXIgaW50ZXItc2VjdGlvbiBjb29yZGluYXRpb24gYW5kIGJldHRlciBwcm9ncmFtbWF0aWMgb3ZlcnNpZ2h0IHdpdGhpbiBVTklDRUYgLS0gdGhpcyB3aWxsIGJlIGV2ZW4gbW9yZSBhcHBhcmVudCBpbiBzZWN0aW9ucyA0YyBhbmQgNGQuIA0KDQo8YnI+DQoNCiMjIyA0Yi4gUGFycmlzaC1sZXZlbCBnYXBzIGluIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZw0KDQpBIHRvdGFsIG9mICoqYHIgcm91bmQoc3VtKHBhcnIwJGJlbl9mcmVxKSAtIHN1bShwYXJyMCRtc19iZW5fbWF4KSwgZGlnaXRzID0gMCkgJT4lIGZvcm1hdChiaWcubWFyayA9ICIsIilgKiogYmVuZWZpY2lhcmllcyByZWNlaXZlZCBzdXBwb3J0IGZyb20gb25seSBvbmUgc2VjdG9yIC0tIHRoaXMgaXMgKipgciByb3VuZCgoc3VtKHBhcnIwJGJlbl9mcmVxKSAtIHN1bShwYXJyMCRtc19iZW5fbWF4KSkgLyBzdW0ocGFycjAkYmVuX2ZyZXEpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzLiBQYXJyaXNoZXMgYmVsb3cgaGF2ZSBiZWVuIHBsb3R0ZWQgYWNjb3JkaW5nIHRvIHRoZWlyIG11bHRpLXNlY3RvciBjb3ZlcmFnZSBhbmQgdGhlaXIgdG90YWwgbnVtYmVyIG9mIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzOyBsYXJnZXIgc2l6ZXMgaW5kaWNhdGUgcGFycmlzaGVzIHdoZXJlIHRoZXJlIGFyZSBoaWdoZXIgbnVtYmVycyBvZiBiZW5lZmljaWFyaWVzIGJlbmVmaXR0aW5nIGZyb20gb25seSBvbmUgc2VjdG9yOiANCg0KYGBge3J9DQptc19zY2F0dGVyIDwtIHBhcnIwICU+JSANCiAgbXV0YXRlKG11bHRpX3NlY3Rvcl9wZXJjZW50ID0gcm91bmQobXNfYmVuX21heCAvIGJlbl9mcmVxICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgIG9uZV9zZWN0b3JfcGVyY2VudCA9IHJvdW5kKChiZW5fZnJlcSAtIG1zX2Jlbl9tYXgpIC8gYmVuX2ZyZXEgKiAxMDAsIGRpZ2l0cyA9IDEpLA0KICAgICAgICAgbXVsdGlfc2VjdG9yX2JlbiA9IHJvdW5kKG1zX2Jlbl9tYXgsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgb25lX3NlY3Rvcl9iZW4gPSByb3VuZChiZW5fZnJlcSAtIG1zX2Jlbl9tYXgsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgYmVuX2ZyZXEgPSByb3VuZChiZW5fZnJlcSwgZGlnaXRzID0gMCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gYmVuX2ZyZXEsIA0KICAgICAgICAgICAgIHkgPSBtdWx0aV9zZWN0b3JfcGVyY2VudCwgDQogICAgICAgICAgICAgdGV4dCA9IHBhc3RlMChwYXJyb3F1aWEsIiwiLCAiXG4iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bmljaXBpbywgIiwiLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0YWRvLCAiLCIsICJcbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAic2VjdG9yIGNvdW50OiAiLCBzZWN0b3JfY291bnQpLA0KICAgICAgICAgICAgIGNvbG91ciA9IGVzdGFkbykpICsNCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG9uZV9zZWN0b3JfYmVuKSwgDQogICAgICAgICAgICAgYWxwaGEgPSAwLjgpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbGFiZWxzID0gbGFiZWxfY29tbWEoYWNjdXJhY3kgPSAxKSkgKw0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgNSkpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKHJlcCgiY29yYWwiLDI0KSkpICsNCiAgeGxhYigiQmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMiKSArIHlsYWIoIlBlcmNlbnRhZ2UgcmVjZWl2ZWQgbXVsdGktc2VjdG9yIHN1cHBvcnQiKSArDQogIGxhYnModGl0bGUgPSAiU2NhdHRlcnBsb3Qgb2YgcGFycmlzaGVzIGJ5IGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGFuZCBtdWx0aS1zZWN0b3IgY292ZXJhZ2UiLCANCiAgICAgICBzaXplID0gIiIsIGNvbG91ciA9ICIiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOC41KSkNCg0KZ2dwbG90bHkobXNfc2NhdHRlciwgdG9vbHRpcCA9IGMoIngiLCAieSIsICJzaXplIiwgInRleHQiKSkgJT4lIA0KICBsYXlvdXQobGVnZW5kID0gbGlzdChmb250ID0gbGlzdChzaXplID0gNikpKSAlPiUgDQogIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IEZBTFNFKSAlPiUgDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgNCiAgICAiU2NhdHRlcnBsb3Qgb2YgcGFycmlzaGVzIGJ5IGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGFuZCBtdWx0aS1zZWN0b3IgY292ZXJhZ2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxzdXA+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJzaXplOiBudW1iZXIgb2YgYmVuZWZpY2lhcmllcyBzdXBwb3J0ZWQgYnkgb25seSBvbmUgc2VjdG9yOyBkb3VibGUtY2xpY2sgc3RhdGUgdG8gdG9nZ2xlIHZpZXc7IG1vdXNlIG92ZXIgZm9yIGRldGFpbHMiLCI8L3N1cD4iKSkpDQoNCmBgYA0KDQpXZSBub3RlIG9ubHkgYSB2ZXJ5IGxvb3NlIHJlbGF0aW9uc2hpcCAoci1zcXVhcmVkID0gYHIgY29yKHBhcnIwJG11bHRpc2VjdG9yX3BlcmNlbnQsIHBhcnIwJGJlbl9mcmVxLCB1c2UgPSAiY29tcGxldGUub2JzIileMiAlPiUgcm91bmQoZGlnaXRzID0gMylgKSBiZXR3ZWVuIHRoZSBudW1iZXIgb2YgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMgYW5kIHRoZSBwZXJjZW50YWdlIG9mIHRob3NlIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIHJlYWNoZWQgYnkgaW50ZXJ2ZW50aW9ucyBmcm9tIG11bHRpcGxlIHNlY3RvcnMuIFRoZXJlIGlzIGxpdHRsZSBlbHNlIGl0IGlzIGNvcnJlbGF0ZWQgd2l0aCBhbmQsIGFzIGNhbiBiZSBzZWVuIGJlbG93LCB0aGVyZSBpcyBubyBkaXNjZXJuaWJsZSBwYXR0ZXJuIHRvIG11bHRpc2VjdG9yIGNvdmVyYWdlLg0KDQpIb3dldmVyLCB3ZSBkbyBub3RlIHRoYXQgaW4gdGhlIHN0YXRlcyB3aGVyZSBVTklDRUYgaGFzIG9mZmljZXMgKEJvbGl2YXIsIFRhY2hpcmEsIFp1bGlhIGFuZCBEaXN0cml0byBDYXBpdGFsKSwgdGhlcmUgaXMgbXVjaCBoaWdoZXIgbXVsdGktc2VjdG9yIGNvdmVyYWdlIHRoYW4gaW4gb3RoZXIgc3RhdGVzLCBwZXJoYXBzIGluZGljYXRpbmcgdGhhdCBhIG1vcmUgZGVjZW50cmFsaXNlZCBhcHByb2FjaCB3aGVyZSBmaWVsZCBvZmZpY2VzIGhhdmUgZ3JlYXRlciBzYXkgaW4gcHJpb3JpdGlzYXRpb24gbWlnaHQgbGVhZCB0byBtb3JlIGNvb3JkaW5hdGlvbiBpbiBtdWx0aS1zZWN0b3IgcHJvZ3JhbW1pbmcuIFRob3VnaCwgdGhhdCB0aGlzIGdyZWF0ZXIgbXVsdGktc2VjdG9yIGNvdmVyYWdlIGhhcyBub3QgZXhwYW5kZWQgb3V0c2lkZSBvZiB0aGVzZSBhcmVhcyBpcyBpbmRpY2F0aXZlIG9mIHRoZSBsZXZlbCBvZiBwbGFubmluZyBhbmQgY29vcmRpbmF0aW9uIGNhcGFjaXR5IGZpZWxkIG9mZmljZXMgYXJlIGNhcGFibGUgb2YuIA0KDQpUaGVyZSBhcmUgdGhlICoqYHIgcGFycjAgJT4lIGZpbHRlcihiZW5fZnJlcSAhPSAwICYgbXNfYmVuX21heCA9PSAwKSAlPiUgbnJvdygpYCoqIHBhcnJpc2hlcyBhdCB0aGUgYm90dG9tIG9mIHRoZSBwbG90OyB0aGVyZSBpcyBvbmx5IG9uZSBzZWN0b3IgcHJlc2VudCBpbiBlYWNoIC0tIHRoaXMgaXMgKipgciByb3VuZCgocGFycjAgJT4lIGZpbHRlcihiZW5fZnJlcSAhPSAwICYgbXNfYmVuX21heCA9PSAwKSAlPiUgbnJvdygpKSAvIChwYXJyMCAlPiUgZmlsdGVyKGJlbl9mcmVxICE9IDApICU+JSBucm93KCkpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIHBhcnJpc2hlcyB3ZSBhcmUgcmVzcG9uZGluZyBpbi4gDQoNCmBgYHtyIGF2Zy1zZWMtc3RhdGUtVEFCTEV9DQoNCnBhcnIwICU+JSANCiAgZmlsdGVyKGJlbmVmaWNpYXJpb3MgIT0gMCkgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBzZWN0b3JfY291bnQpICU+JSANCiAgZ3JvdXBfYnkoZXN0YWRvKSAlPiUgDQogIHN1bW1hcmlzZShhdmdfc2VjdG9yID0gcm91bmQobWVhbihzZWN0b3JfY291bnQpLCBkaWdpdHMgPSAyKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MoYXZnX3NlY3RvcikpICU+JSANCiAgZmlsdGVyKGF2Z19zZWN0b3IgPiAyIHwgYXZnX3NlY3RvciA8IDEuMTkpICU+JSANCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGVzdGFkbywgdmFsdWVzX2Zyb20gPSBhdmdfc2VjdG9yKSAlPiUgDQogIG11dGF0ZShgfHxgID0gYygiIikpICU+JSByZWxvY2F0ZShgfHxgLCAuYWZ0ZXIgPSBCT0xJVkFSKSAlPiUgDQogIHBhbmRlcihjYXB0aW9uID0gIlRvcCA1IGFuZCBib3R0b20gNSBzdGF0ZXMsIGF2ZXJhZ2UgbnVtYmVyIG9mIHNlY3RvcnMgcGVyIHBhcnJpc2giLCBtaXNzaW5nID0gIiIpDQoNCmBgYA0KDQoNCjxicj4NCg0KIyMjIDRjLiBDbHVzdGVyIGNvbWJpbmF0aW9ucw0KDQpUaGlzIHNlY3Rpb24gd2lsbCBleGFtaW5lIHRoZSBwYXJyaXNoZXMgdGhhdCBoYXZlIG11bHRpLXNlY3RvciBjb3ZlcmFnZSBhbmQgdGhlIHR5cGVzIG9mIGludGVyLWNsdXN0ZXIgY29tYmluYXRpb25zIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZW0uIExldCB1cyBiZWdpbiB3aXRoIGFuIG92ZXJ2aWV3IG9mIHRoZSBnZW9ncmFwaGljIHJlYWNoIG9mIGVhY2ggY2x1c3RlciAtLSB3ZSB1c2UgZnJlcXVlbmNpZXMgaGVyZSwgYXMgZWFjaCBpbmRpdmlkdWFsIG1pZ2h0IGhhdmUgYmVuZWZpdHRlZCBmcm9tIG11bHRpcGxlIGNvbWJpbmF0aW9ucyBvZiBjbHVzdGVyczogDQoNCmBgYHtyIGNsdXN0LVRBQkxFfQ0KYWN0X2JlbiAlPiUgDQogIGZpbHRlcihzZWN0b3IgIT0gIlNlZ3VyaWRhZF9BbGltZW50YXJpYSIgJiBjYXRlZ29yaWEgIT0gIlZBQ1VOQUNJT04iKSAlPiUgDQogIG11dGF0ZShzZWN0b3IgPSBpZmVsc2Uoc3RyX2RldGVjdChzZWN0b3IsICJQcm90ZWNjaW9uX0dCVnxQcm90ZWNjaW9uX0dlbmVyYWx8UHJvdGVjY2lvbl9OTkEiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIlByb3RlY2Npb24iLCBzZWN0b3IpKSAlPiUgDQogICMgbXV0YXRlKHNlY3RvciA9IGlmZWxzZShjYXRlZ29yaWEgPT0gIlZBQ1VOQUNJT04iLCAiVmFjdW5hY2lvbiIsIHNlY3RvcikpDQogICMgd2UncmUgbm90IGdvaW5nIHRvIGxvb2sgYXQgdmFjY2luYXRpb24gaW4gdGhpcyByZXBvcnQgDQogIGdyb3VwX2J5KHNlY3RvcikgJT4lIA0KICBzdW1tYXJpc2UocGFycmlzaGVzID0gbl9kaXN0aW5jdChwY29kZTMpLA0KICAgICAgICAgICAgYmVuZWZpY2lhcnlfZnJlcXVlbmNpZXMgPSBzdW0oYmVuZWZpY2lhcmlvcykpICU+JSANCiAgcmVuYW1lKGNsdXN0ZXIgPSBzZWN0b3IpICU+JSANCiAgcGFuZGVyKGNhcHRpb24gPSAiQ2x1c3RlciBzdW1tYXJ5LCB2YWNjaW5hdGlvbiBleGx1ZGVkIiwgYmlnLm1hcmsgPSAiLCIsIHN0eWxlID0gInJtYXJrZG93biIsIA0KICAgICAgICAganVzdGlmeSA9IGMoImxlZnQiLCAicmlnaHQiLCAicmlnaHQiKSkNCiAgDQpgYGANCjxicj4gDQoNCk5leHQsIHdlIHdpbGwgc3VtbWFyaXNlIHRoZSBpbnRlci1jbHVzdGVyIGNvbWJpbmF0aW9ucyBhY2NvcmRpbmcgdG86IA0KDQoqICoqYGNvbWJpbmF0aW9uYCoqLCByZWZlcnJpbmcgdG8gdGhlIHZhcmlvdXMgY2x1c3Rlci13aXNlIHBhaXJzIHRoYXQgZXhpc3Q7IA0KKiAqKmBwYXJyaXNoZXNgKiosIGluZGljYXRpbmcgdGhlIG51bWJlciBvZiBwYXJyaXNoZXMgZWFjaCBjb21iaW5hdGlvbiBpcyBwcmVzZW50IGluOyANCiogKipgY2x1c3RlcjFgKiogYW5kICoqYGNsdXN0ZXIyYCoqLCB3aGljaCBzaG93IHRoZSBudW1iZXIgb2YgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMgcmVhY2hlZCBieSBib3RoIGNsdXN0ZXJzIGluIGVhY2ggcGFpciwgaW4gdGhlIG9yZGVyIHRoYXQgdGhleSBhcHBlYXIgaW4gKipgY29tYmluYXRpb25gKiouIA0KKiAqKmBwYWlyX3N1bWAqKiwgd2hpY2ggc2hvd3MgdGhlIHRvdGFsIG51bWJlciBvZiBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBpbiB0aGF0IHBhaXIgaS5lLiB0aGUgcGFpcl9zdW0gZm9yIGVkdV9udXQgd291bGQgYmUgdGhlIHN1bSBvZiBlZHVjYXRpb24gYW5kIG51dHJpdGlvbiBiZW5lZmljaWFyaWVzLiANCiogKipgJW1zX21heGAqKiwgd2hpY2ggc2hvd3MgdGhlIG1heGltdW0gcGVyY2VudGFnZSBvZiBtdWx0aXNlY3RvciBiZW5lZmljaWFyaWVzIG9mIGVhY2ggcGFpciBpLmUuIGlmIHRoZSBwYWlyIGVkdS1udXQgaGFzIDEwIGVkdWNhdGlvbiBiZW5lZmljaWFyaWVzIGFuZCAzMCBudXRyaXRpb24gYmVuZWZpY2lhcmllcywgdGhlIG1heGltdW0gbnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgd2hpY2ggcmVjZWl2ZWQgc3VwcG9ydCBmcm9tIGJvdGggc2VjdG9ycyBpcyAxMCwgcmVzdWx0aW5nIGluIGEgYCVfbXNfbWF4YCBvZiAyNSUuIEJ1dCwgYXMgbWVudGlvbmVkIGluIHRoZSBub3RlcyBmb3Igc2VjdGlvbiA0YSwgdGhpcyBpcyBhIHRoZW9yZXRpY2FsIG1heGltdW0gYW5kIHRoZSBhY3R1YWwgbGV2ZWwgb2YgY29pbmNpZGVuY2UgaXMgbGlrZWx5IG11Y2ggbG93ZXIuDQoNCmBgYHtyIGNsdXN0LWNvbS1SRUYtYW5kLVRBQkxFfQ0KIyBjcmVhdGlvbiBvZiByZWZlcmVuY2UgZGYgZm9yIHRoZSBjbHVzdGVyIGNvbWJpbmF0aW9ucyANCmNsdXN0X2NvbSA8LSBwYXJyICU+JSANCiAgZmlsdGVyKGJlbl9mcmVxICE9IDApICU+JSANCiAgc2VsZWN0KHBjb2RlMywgYmVuX2ZyZXEsIGVkdWNhY2lvbl9iZW4sIG51dHJpY2lvbl9iZW4sIHNhbHVkX2Jlbiwgd2FzaF9iZW4sIHByb3RlY2Npb25fYmVuKSAlPiUNCiAgIyBtdXRhdGUgYSBuZXcgY29sdW1uIGZvciBlYWNoIGNvbWJpbmF0aW9uIG9mIHNlY3RvcnMgLS0gaWYgZWR1IGlzIHRoZSBmaXJzdCBjbHVzdGVyIGluIHRoZSBjb21iaW5hdGlvbiwgDQogICMgb25seSBlZHVjYXRpb24gYmVuZWZpY2lhcmllcyB3aWxsIGJlIHVzZWQgdG8gZmlsbCB2YWx1ZXMgaW4gdGhlIGNvbHVtbiANCiAgbXV0YXRlKGVkdV9vbmx5ID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPT0gYmVuX2ZyZXEsIGVkdWNhY2lvbl9iZW4sIDApLA0KICAgICAgICAgZWR1X251dCA9IGlmZWxzZShlZHVjYWNpb25fYmVuID4gMCAmIG51dHJpY2lvbl9iZW4gPiAwLCBlZHVjYWNpb25fYmVuICsgbnV0cmljaW9uX2JlbiwgMCksDQogICAgICAgICBlZHVfc2FsID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPiAwICYgc2FsdWRfYmVuID4gMCwgZWR1Y2FjaW9uX2JlbiArIHNhbHVkX2JlbiwgMCksDQogICAgICAgICBlZHVfd2FzaCA9IGlmZWxzZShlZHVjYWNpb25fYmVuID4gMCAmIHdhc2hfYmVuID4gMCwgZWR1Y2FjaW9uX2JlbiArIHdhc2hfYmVuLCAwKSwNCiAgICAgICAgIGVkdV9wcm90ID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPiAwICYgcHJvdGVjY2lvbl9iZW4gPiAwLCBlZHVjYWNpb25fYmVuICsgcHJvdGVjY2lvbl9iZW4sIDApLA0KICAgICAgICAgbnV0X29ubHkgPSBpZmVsc2UobnV0cmljaW9uX2JlbiA9PSBiZW5fZnJlcSwgbnV0cmljaW9uX2JlbiwgMCksDQogICAgICAgICBudXRfc2FsID0gaWZlbHNlKG51dHJpY2lvbl9iZW4gPiAwICYgc2FsdWRfYmVuID4gMCwgbnV0cmljaW9uX2JlbiArIHNhbHVkX2JlbiwgMCksIA0KICAgICAgICAgbnV0X3dhc2ggPSBpZmVsc2UobnV0cmljaW9uX2JlbiA+IDAgJiB3YXNoX2JlbiA+IDAsIG51dHJpY2lvbl9iZW4gKyB3YXNoX2JlbiwgMCksIA0KICAgICAgICAgbnV0X3Byb3QgPSBpZmVsc2UobnV0cmljaW9uX2JlbiA+IDAgJiBwcm90ZWNjaW9uX2JlbiA+IDAsIG51dHJpY2lvbl9iZW4gKyBwcm90ZWNjaW9uX2JlbiwgMCksDQogICAgICAgICBzYWxfb25seSA9IGlmZWxzZShzYWx1ZF9iZW4gPT0gYmVuX2ZyZXEsIHNhbHVkX2JlbiwgMCksDQogICAgICAgICBzYWxfd2FzaCA9IGlmZWxzZShzYWx1ZF9iZW4gPiAwICYgd2FzaF9iZW4gPiAwLCBzYWx1ZF9iZW4gKyB3YXNoX2JlbiwgMCksDQogICAgICAgICBzYWxfcHJvdCA9IGlmZWxzZShwcm90ZWNjaW9uX2JlbiA+IDAgJiBzYWx1ZF9iZW4gPiAwLCBzYWx1ZF9iZW4gKyBwcm90ZWNjaW9uX2JlbiwgMCksDQogICAgICAgICB3YXNoX29ubHkgPSBpZmVsc2Uod2FzaF9iZW4gPT0gYmVuX2ZyZXEsIHdhc2hfYmVuLCAwKSwNCiAgICAgICAgIHByb3Rfd2FzaCA9IGlmZWxzZSh3YXNoX2JlbiA+IDAgJiBwcm90ZWNjaW9uX2JlbiA+IDAsIHdhc2hfYmVuICsgcHJvdGVjY2lvbl9iZW4sIDApLA0KICAgICAgICAgcHJvdF9vbmx5ID0gaWZlbHNlKHByb3RlY2Npb25fYmVuID09IGJlbl9mcmVxLCBwcm90ZWNjaW9uX2JlbiwgMCkpICU+JSANCiAgIyBwaXZvdF9sb25nZXIgdG8gdGhlIGNsdXN0X2ZyZXEgY29sdW1uIA0KICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiY29tYmluYXRpb24iLCB2YWx1ZXNfdG8gPSAicGFpcl9zdW0iLCA4OjIyKSAlPiUNCiAgZmlsdGVyKHBhaXJfc3VtICE9IDApICU+JSANCiAgZ3JvdXBfYnkocGNvZGUzLCBjb21iaW5hdGlvbikgJT4lIA0KICBzdW1tYXJpc2UoZWR1Y2FjaW9uX2JlbiA9IG1lYW4oZWR1Y2FjaW9uX2JlbiksDQogICAgICAgICAgICBudXRyaWNpb25fYmVuID0gbWVhbihudXRyaWNpb25fYmVuKSwNCiAgICAgICAgICAgIHNhbHVkX2JlbiA9IG1lYW4oc2FsdWRfYmVuKSwNCiAgICAgICAgICAgIHdhc2hfYmVuID0gbWVhbih3YXNoX2JlbiksDQogICAgICAgICAgICBwcm90ZWNjaW9uX2JlbiA9IG1lYW4ocHJvdGVjY2lvbl9iZW4pLA0KICAgICAgICAgICAgcGFpcl9zdW0gPSBzdW0ocGFpcl9zdW0pKSAlPiUgDQogICMgY2FsY3VsYXRpbmcgdGhlIHN1bSBvZiBmcmVxdWVuY2llcyBpbiBlYWNoIHBhaXINCiAgbXV0YXRlKGNsdXN0ZXIxID0gDQogICAgICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X251dCIpIH4gZWR1Y2FjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3NhbCIpIH4gZWR1Y2FjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3dhc2giKSB+IGVkdWNhY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgImVkdV9wcm90IikgfiBlZHVjYWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfc2FsIikgfiBudXRyaWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfd2FzaCIpIH4gbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAibnV0X3Byb3QiKSB+IG51dHJpY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF93YXNoIikgfiBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF9wcm90IikgfiBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInByb3Rfd2FzaCIpIH4gcHJvdGVjY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgImVkdV9vbmx5IikgfiBlZHVjYWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfb25seSIpIH4gbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAic2FsX29ubHkiKSB+IHNhbHVkX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAid2FzaF9vbmx5IikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAicHJvdF9vbmx5IikgfiBwcm90ZWNjaW9uX2JlbikpICU+JQ0KICBtdXRhdGUoY2x1c3RlcjIgPSANCiAgICAgICAgICAgY2FzZV93aGVuKA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJlZHVfbnV0IikgfiAgbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3NhbCIpIH4gIHNhbHVkX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3dhc2giKSB+IHdhc2hfYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJlZHVfcHJvdCIpIH4gcHJvdGVjY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgIm51dF9zYWwiKSB+ICBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgIm51dF93YXNoIikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAibnV0X3Byb3QiKSB+IHByb3RlY2Npb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJzYWxfd2FzaCIpIH4gd2FzaF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF9wcm90IikgfiBwcm90ZWNjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAicHJvdF93YXNoIikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAib25seSQiKSB+IDApKSAlPiUNCiAgc2VsZWN0KHBjb2RlMywgY29tYmluYXRpb24sIGNsdXN0ZXIxLCBjbHVzdGVyMiwgcGFpcl9zdW0pDQoNCiMgcGFuZGVyIHRhYmxlIGNsdXN0ZXIgY29tYmluYXRpb25zIA0KcmJpbmQoDQpjbHVzdF9jb20gJT4lICANCiAgZmlsdGVyKHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJvbmx5JCIpKSAlPiUgDQogIGdyb3VwX2J5KGNvbWJpbmF0aW9uKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyaXNoZXMgPSBuKCksDQogICAgICAgICAgICBjbHVzdGVyMSA9IHN1bShjbHVzdGVyMSksDQogICAgICAgICAgICBjbHVzdGVyMiA9IHN1bShjbHVzdGVyMiksDQogICAgICAgICAgICBwYWlyX3N1bSA9IHN1bShwYWlyX3N1bSkpICU+JSANCiAgbXV0YXRlKGAlbXNfbWF4YCA9IHBtaW4oY2x1c3RlcjEsIGNsdXN0ZXIyKSAvIHBhaXJfc3VtICogMTAwLA0KICAgICAgICAgYCVtc19tYXhgID0gcm91bmQoaWZlbHNlKGlzLm5hbihgJW1zX21heGApLCAwLCBgJW1zX21heGApLCBkaWdpdHMgPSAxKSkgJT4lIA0KICBhcnJhbmdlKGRlc2MocGFpcl9zdW0pKSAlPiUgDQogIHJiaW5kKE5BKSwNCg0KY2x1c3RfY29tICU+JSAgDQogIGZpbHRlcighc3RyX2RldGVjdChjb21iaW5hdGlvbiwgIm9ubHkkIikpICU+JSANCiAgZ3JvdXBfYnkoY29tYmluYXRpb24pICU+JSANCiAgc3VtbWFyaXNlKHBhcnJpc2hlcyA9IG4oKSwNCiAgICAgICAgICAgIGNsdXN0ZXIxID0gc3VtKGNsdXN0ZXIxKSwNCiAgICAgICAgICAgIGNsdXN0ZXIyID0gc3VtKGNsdXN0ZXIyKSwNCiAgICAgICAgICAgIHBhaXJfc3VtID0gc3VtKHBhaXJfc3VtKSkgJT4lIA0KICBtdXRhdGUoYCVtc19tYXhgID0gcG1pbihjbHVzdGVyMSwgY2x1c3RlcjIpIC8gcGFpcl9zdW0gKiAxMDAsDQogICAgICAgICBgJW1zX21heGAgPSByb3VuZChpZmVsc2UoaXMubmFuKGAlbXNfbWF4YCksIDAsIGAlbXNfbWF4YCksIGRpZ2l0cyA9IDEpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhwYWlyX3N1bSkpDQoNCikgJT4lIA0KDQogIHBhbmRlcihjYXB0aW9uID0gIkNsdXN0ZXIgY29tYmluYXRpb25zLCBzb3J0ZWQgYnkgcGFpcl9zdW0iLCBiaWcubWFyayA9ICIsIiwgbWlzc2luZyA9ICIiLCAgDQogICAgICAgICBqdXN0aWZ5ID0gYygibGVmdCIsICJyaWdodCIsICJyaWdodCIsICJyaWdodCIsICJyaWdodCIsICJyaWdodCIpKQ0KICANCmBgYA0KDQo8YnI+DQoNClRoZSBtb3N0IGNvbW1vbiBwYWlyaW5nIHdhcyBiZXR3ZWVuIHRoZSBOdXRyaXRpb24gYW5kIEVkdWNhdGlvbiBjbHVzdGVycyAtLSB0aGV5IGNvaW5jaWRlIGluIGByIGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJlZHVfbnV0IikgJT4lIG5yb3coKWAgcGFycmlzaGVzLCBmb2xsb3dlZCBieSBOdXRyaXRpb24gYW5kIFByb3RlY3Rpb24uIEluIHRoZSBuZXh0IHNlY3Rpb24sIHdlIHdpbGwgaW52ZXN0aWdhdGUgd2hldGhlciB0aGUgc3Vic3RhbnRpYWwgb3ZlcmxhcCBiZXR3ZWVuIE51dHJpdGlvbiBhbmQgUHJvdGVjdGlvbiBhdCB0aGUgcGFycmlzaCBsZXZlbCB3YXMgY29vcmRpbmF0ZWQgb3IgLS0gYXMgaW4gdGhlIGNhc2Ugd2l0aCBpdHMgb3ZlcmxhcCB3aXRoIEVkdWNhdGlvbiwgd2hlcmUgdGhlcmUgYXJlIG5vIGNvbmNyZXRlIHByb2dyYW1tYXRpYyBsaW5rcyAtLSBkdWUgbW9yZSB0byBpdHMgd2lkZSBvcGVyYXRpb25hbCBwcmVzZW5jZS4gIA0KDQpQcm90ZWN0aW9uIGFuZCBXQVNILCBob3dldmVyLCBib3RoIGRvIGhhdmUgZXhwbGljaXQgcHJvZ3JhbW1hdGljIGxpbmtzIChpbiB0aGUgbG9nZnJhbWUpIHdpdGggRWR1Y2F0aW9uIGFuZCBgciBjbHVzdF9jb20gJT4lIGZpbHRlcihjb21iaW5hdGlvbiA9PSAiZWR1X3Byb3QiKSAlPiUgbnJvdygpYCBhbmQgYHIgY2x1c3RfY29tICU+JSBmaWx0ZXIoY29tYmluYXRpb24gPT0gImVkdV93YXNoIikgJT4lIG5yb3coKWAgcGFycmlzaGVzIHJlc3BlY3RpdmVseS4gQSBmcnVpdGZ1bCBhdmVudWUgb2YgaW52ZXN0aWdhdGlvbiB3b3VsZCBiZSBob3cgbWFueSBiZW5lZmljaWFyaWVzIG9mIEVkdWNhdGlvbiBhbHNvIGJlbmVmaXR0ZWQgZnJvbSBQcm90ZWN0aW9uIGludGVydmVudGlvbnMgYW5kIGhvdyBjbG9zZSBpdCBpcyB0byB0aGUgMzcuOCUgdGhlb3JldGljYWwgbWF4aW11bS4NCg0KTnV0cml0aW9uIG9wZXJhdGVzIGFsb25lIGluIGByIGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJudXRfb25seSIpICU+JSBucm93KClgIHBhcnJpc2hlcyBvdXQgb2YgdGhlIGByIGFjdF9iZW4gJT4lIGZpbHRlcihzZWN0b3IgPT0gIk51dHJpY2lvbiIpICU+JSBkaXN0aW5jdChwY29kZTMpICU+JSBucm93KClgIHRoYXQgaXQgaXMgcHJlc2VudCBpbiwgdGhpcyBpcyB0aGUgbW9zdCBvdXQgb2YgYW55IG9mIHRoZSBvdGhlciBjbHVzdGVycyAtLSBpdCBpcyBuZWNlc3NhcnkgdG8gZXZhbHVhdGUgdGhlIGV4dGVudCB0byB3aGljaCBvdGhlciBjbHVzdGVycyBjYW4gbWFrZSB1c2Ugb2YgdGhlIGZvb3Rob2xkcyBlc3RhYmxpc2hlZCBieSBOdXRyaXRpb24uIA0KDQpXaGlsc3QgTnV0cml0aW9uIGFuZCBIZWFsdGggaGF2ZSBleGNlbGxlbnQgcHJvZ3JhbW1hdGljIGNvbXBsZW1lbnRhcml0eSwgZXNwZWNpYWxseSB3aXRoIEhlYWx0aCdzIGZvY3VzIG9uIG9ic3RldHJpYywgYW50ZW5hdGFsIGFuZCBuZW9uYXRhbCBjYXJlLCB0aGlzIGNvbWJpbmF0aW9uIGhhcyB0aGUgbG93ZXN0IG51bWJlciBvZiBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBvZiBhbGwgdGhlIGNvbWJpbmF0aW9ucy4gDQoNCkFsbW9zdCBub25lIG9mIFdBU0gncyBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBvY2N1cnJlZCBpbiBwYXJyaXNoZXMgd2hlcmUgbm8gb3RoZXIgY2x1c3RlcnMgd2VyZSBwcmVzZW50LiBJdHMgZ3JlYXQgcmVhY2ggYW5kIGJsYW5rZXQgY292ZXJhZ2UgKGVzcGVjaWFsbHkgd2F0ZXIgc3VwcGx5IGFuZCBvdGhlciBjb21tdW5pdHktbGV2ZWwgYWN0aXZpdGllcykgbWVhbiB0aGF0IG90aGVyIGNsdXN0ZXJzIG9wZXJhdGluZyBpbiB0aGUgc2FtZSBhcmVhcyBhcyBXQVNIIGFyZSAiZ3VhcmFudGVlZCIgdG8gcmVhY2ggYmVuZWZpY2lhcmllcyB3aXRoIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZyAtLSB0aGUgY2hhbGxlbmdlcyBvZiB0aGVzZSBjb21iaW5hdGlvbnMgYmVpbmcgDQoxLiB0aGUgaW50ZW50aW9uYWxpdHkgb2YgdGhlIG11bHRpLXNlY3RvciBjb3ZlcmFnZSBhbmQgDQoyLiBtYXRjaGluZyB0aGUgc2NhbGUgb2YgV0FTSCBhY3Rpdml0aWVzLiANCldBU0ggaGFzIGV4Y2VsbGVudCBwcm9ncmFtbWF0aWMgb3ZlcmxhcCB3aXRoIGFsbCBvdGhlciBjbHVzdGVycy4gV0FTSCBpcyB0aGUgb25seSBzZWN0b3IgdG8gcHJvZ3JhbW1lIHNwZWNpZmljIG11bHRpLXNlY3RvciBpbnRlcnZlbnRpb25zIC0tIFdBU0ggaW4gc2Nob29scyBhbmQgV0FTSCBpbiBoZWFsdGgvbnV0cml0aW9uIGNlbnRyZXMuIA0KDQpMaWtlIFdBU0ggYW5kIEhlYWx0aCwgUHJvdGVjdGlvbiBoYXMgdmVyeSBsaW1pdGVkIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGluIHBhcnJpc2hlcyB3aGVyZSBpdCBvcGVyYXRlcyBhbG9uZS4gUHJvdGVjdGlvbiBjb2luY2lkZXMgdGhlIG1vc3Qgd2l0aCBOdXRyaXRpb24gLS0gdGhpcyBzaG91bGQgc2VydmUgYXMgYW4gaW1wdWxzZSBmb3IgdGhlIGNyZWF0aW9uIG9mIHJlZmVycmFsIHBhdGh3YXlzIGJldHdlZW4gdGhlIHR3byBzaW5jZSBib3RoIGNhcnJ5IG91dCBzY3JlZW5pbmcgYWN0aXZpdGllcywgbWFkZSBlYXNpZXIgYnkgdGhlIGZhY3QgdGhhdCBib3RoIG1hbmFnZSBzb21lIGZvcm0gb2YgYmVuZWZpY2lhcnktbGV2ZWwgZGF0YWJhc2UuIFByb3RlY3Rpb24gaGFzIHRoZSBtb3N0IGV4cGxpY2l0IHByb2dhbW1hdGljIGxpbmtzIHRvIEVkdWNhdGlvbiBpbiB0aGUgbG9nZnJhbWUuDQoNCjxicj4NCg0KIyMjIDRkLiBBY3Rpdml0eSBjYXRlZ29yaWVzIA0KDQpUbyBjbG9zZSwgdGhlIHN0YXRlIG9mIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZyBpcyBwb29yLiBUaGVyZSBpcyBsaXR0bGUgaW50ZW50aW9uYWxpdHkgaW4gd2hpY2ggYXJlYXMgaGF2ZSBtdWx0aS1zZWN0b3IgY292ZXJhZ2UgYW5kIHdoaWNoIGFyZWFzIGRvIG5vdCAtLSBtdWx0aS1zZWN0b3IgbGlua3MgZG8gZXhpc3QgYXQgdGhlIGFjdGl2aXR5IGxldmVsLCBidXQgdGhpcyBpcyBhIHBvb3IgYXBwcm94aW1hdGlvbiBvZiBkZXZlbG9waW5nIGEgcHJvZ3JhbW1lIGJhc2VkIG9uIHRoZSBzcGVjaWZpYyBuZWVkcyBvZiBhIHRhcmdldCBhcmVhLiBBbmQgd2Ugc2VlIHRoZSB3ZWFrbmVzcyBvZiB0aGlzIGFwcHJvYWNoIGluIHRoZSB0YWJsZSBiZWxvdyB3aGljaCBsaXN0cyB0aGUgbW9zdCBjb21tb24gaW50ZXItY2x1c3RlciBhY3Rpdml0eSBjYXRlZ29yeSBjb21iaW5hdGlvbnMgYXQgdGhlIHBhcnJpc2ggbGV2ZWwuICANCg0KYGBge3IgY2MtY2F0ZWdvcmlhLVRBQkxFfQ0KDQpjYXQgPC0gYWN0X2JlbiAlPiUgDQogIGZpbHRlcihjYXRlZ29yaWEgIT0gIlZBQ1VOQUNJT04iICYgY2F0ZWdvcmlhICE9ICJPVFJPIikgJT4lIA0KICBncm91cF9ieShwY29kZTMsIGNhdGVnb3JpYSkgJT4lIA0KICBzdW1tYXJpc2UoYmVuZWZpY2lhcmlvcyA9IHN1bShiZW5lZmljaWFyaW9zKSkgJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gY2F0ZWdvcmlhLCB2YWx1ZXNfZnJvbSA9IGJlbmVmaWNpYXJpb3MpICU+JQ0KICByZXBsYWNlKGlzLm5hKC4pLCAwKSAlPiUgDQogIGdyb3VwX2J5KHBjb2RlMykgJT4lIA0KICBzdW1tYXJpc2UoYWNyb3NzKGV2ZXJ5dGhpbmcoKSwgfiBzdW0oLiwgaXMubmEoLiksIDApKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lIA0KICBtdXRhdGUoUFJFVkVOQ0lPTl9ERVNOVVRSSUNJT05fQUdVREEgPSBpZmVsc2UoUFJFVkVOQ0lPTl9ERVNOVVRSSUNJT05fQUdVREEgIT0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUkVWRU5DSU9OX0RFU05VVFJJQ0lPTl9BR1VEQSIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgQ0FQQUNJVEFDSU9ORVNfUFJPVEVDQ0lPTiA9IGlmZWxzZShDQVBBQ0lUQUNJT05FU19QUk9URUNDSU9OICE9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVBBQ0lUQUNJT05FU19QUk9URUNDSU9OIixOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIFRSQVRBTUlFTlRPX0RFU05VVFJJQ0lPTl9BR1VEQSA9IGlmZWxzZShUUkFUQU1JRU5UT19ERVNOVVRSSUNJT05fQUdVREEgIT0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVFJBVEFNSUVOVE9fREVTTlVUUklDSU9OX0FHVURBIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBBU0lTVEVOQ0lBX0FMSU1FTlRBUklBID0gaWZlbHNlKEFTSVNURU5DSUFfQUxJTUVOVEFSSUEgIT0gMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBU0lTVEVOQ0lBX0FMSU1FTlRBUklBIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBSRVNJTEVOQ0lBX0VEVUNBQ0lPTiA9IGlmZWxzZShSRVNJTEVOQ0lBX0VEVUNBQ0lPTiAhPSAwLCAiUkVTSUxFTkNJQV9FRFVDQUNJT04iLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIEZPUlRBTEVDSU1JRU5UT19JTlNUSVRVQ0lPTkFMID0gaWZlbHNlKEZPUlRBTEVDSU1JRU5UT19JTlNUSVRVQ0lPTkFMICE9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGT1JUQUxFQ0lNSUVOVE9fSU5TVElUVUNJT05BTCIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgV0FTSF9FTl9FRFVDQUNJT04gPSBpZmVsc2UoV0FTSF9FTl9FRFVDQUNJT04gIT0gMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0FTSF9FTl9FRFVDQUNJT04iLCBOQV9jaGFyYWN0ZXJfKSwgDQogICAgICAgICBTRUdVUklEQURfQUxJTV9JTlNUSVRVQ0lPTkFMID0gaWZlbHNlKFNFR1VSSURBRF9BTElNX0lOU1RJVFVDSU9OQUwgIT0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFR1VSSURBRF9BTElNX0lOU1RJVFVDSU9OQUwiLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIFZJSCA9IGlmZWxzZShWSUggIT0gMCwgIlZJSCIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgU0FMVURfUE9CTEFDSU9OQUwgPSBpZmVsc2UoU0FMVURfUE9CTEFDSU9OQUwgIT0gMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0FMVURfUE9CTEFDSU9OQUwiLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIFBST1ZJU0lPTl9ERV9TRVJWSUNJTyA9IGlmZWxzZShQUk9WSVNJT05fREVfU0VSVklDSU8gIT0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUFJPVklTSU9OX0RFX1NFUlZJQ0lPIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBJTkNJREVOQ0lBX0NPTl9BVVRPUklEQURFUyA9IGlmZWxzZShJTkNJREVOQ0lBX0NPTl9BVVRPUklEQURFUyAhPSAwLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklOQ0lERU5DSUFfQ09OX0FVVE9SSURBREVTIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBDT01VTklEQURFU19TQUxVRCA9IGlmZWxzZShDT01VTklEQURFU19TQUxVRCAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDT01VTklEQURFU19TQUxVRCIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgUkVEX0lOVEVHUkFEQV9TQUxVRCA9IGlmZWxzZShSRURfSU5URUdSQURBX1NBTFVEICE9IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUkVEX0lOVEVHUkFEQV9TQUxVRCIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgSU5GT1JNQUNJT05fUklFU0dPUyA9IGlmZWxzZShJTkZPUk1BQ0lPTl9SSUVTR09TICE9IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSU5GT1JNQUNJT05fUklFU0dPUyIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgUFJPVklTSU9OX0RFX1NFUlZJQ0lPUyA9IGlmZWxzZShQUk9WSVNJT05fREVfU0VSVklDSU9TICE9IDAsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUk9WSVNJT05fREVfU0VSVklDSU9TIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBQUk9NT0NJT05fSElHSUVORSA9IGlmZWxzZShQUk9NT0NJT05fSElHSUVORSAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQUk9NT0NJT05fSElHSUVORSIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgQUdVQV9FTl9DT01VTklEQURFUyA9IGlmZWxzZShBR1VBX0VOX0NPTVVOSURBREVTICE9IDAsICJBR1VBX0VOX0NPTVVOSURBREVTIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBXQVNIX0VOX1NBTFVEX05VVFJJQ0lPTiA9IGlmZWxzZShXQVNIX0VOX1NBTFVEX05VVFJJQ0lPTiAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXQVNIX0VOX1NBTFVEX05VVFJJQ0lPTiIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgRk9SVEFMRUNJTUlFTlRPX0NBUEFDSURBRF9FRFVDQUNJT04gPSBpZmVsc2UoRk9SVEFMRUNJTUlFTlRPX0NBUEFDSURBRF9FRFVDQUNJT04gIT0gMCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGT1JUQUxFQ0lNSUVOVE9fQ0FQQUNJREFEX0VEVUNBQ0lPTiIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgQUNDRVNPX1BFUk1BTkVOQ0lBX0VTQ09MQVIgPSBpZmVsc2UoQUNDRVNPX1BFUk1BTkVOQ0lBX0VTQ09MQVIgIT0gMCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQUNDRVNPX1BFUk1BTkVOQ0lBX0VTQ09MQVIiLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIFNBTFVEX01BVEVSTkFfSU5GQU5USUwgPSBpZmVsc2UoU0FMVURfTUFURVJOQV9JTkZBTlRJTCAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNBTFVEX01BVEVSTkFfSU5GQU5USUwiLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIFNVTUlOSVNUUk9TX01FRElDQU1FTlRPU19CQVNJQ09TID0gaWZlbHNlKFNVTUlOSVNUUk9TX01FRElDQU1FTlRPU19CQVNJQ09TICE9IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNVTUlOSVNUUk9TX01FRElDQU1FTlRPU19CQVNJQ09TIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBTQU5FQU1JRU5UTyA9IGlmZWxzZShTQU5FQU1JRU5UTyAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTQU5FQU1JRU5UTyIsIE5BX2NoYXJhY3Rlcl8pLA0KICAgICAgICAgUkVEX0RFX1BST1RFQ0NJT04gPSBpZmVsc2UoUkVEX0RFX1BST1RFQ0NJT04gIT0gMCwgIlJFRF9ERV9QUk9URUNDSU9OIiwgTkFfY2hhcmFjdGVyXyksDQogICAgICAgICBDQVBBQ0lUQUNJT05FU19OVVRSSUNJT04gPSBpZmVsc2UoQ0FQQUNJVEFDSU9ORVNfTlVUUklDSU9OICE9IDAsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDQVBBQ0lUQUNJT05FU19OVVRSSUNJT04iLCBOQV9jaGFyYWN0ZXJfKSwNCiAgICAgICAgIEVTVEFCTEVDSU1JRU5UT1NfU0FMVUQgPSBpZmVsc2UoRVNUQUJMRUNJTUlFTlRPU19TQUxVRCAhPSAwLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkVTVEFCTEVDSU1JRU5UT1NfU0FMVUQiLCBOQV9jaGFyYWN0ZXJfKSkgIA0KDQpjYXRfY29tYjwtIHQoY29tYm4oc29ydChuYS5vbWl0KHVuaXF1ZSh1bmxpc3QoY2F0WywtMV0pKSkpLCAyKSkNCg0KY2F0X2ZyZXFzIDwtIGFwcGx5KGNhdF9jb21iLCAxLCBmdW5jdGlvbihDKSB7DQogIHN1bShhcHBseShjYXRbLC0xXSwgMSwgZnVuY3Rpb24oYSkgYWxsKEMgJWluJSBhLCBuYS5ybSA9IFRSVUUpKSkNCn0pDQoNCmFzLmRhdGEuZnJhbWUoY2F0X2NvbWIpICU+JSANCiAgbXV0YXRlKGNvdW50ID0gY2F0X2ZyZXFzKSAlPiUgDQogIGxlZnRfam9pbihhY3RfYmVuICU+JSBzZWxlY3QoY2x1c3RlcjEgPSBzZWN0b3IsIFYxID0gY2F0ZWdvcmlhKSAlPiUgZGlzdGluY3QoKSwgYnkgPSAiVjEiKSAlPiUgDQogIGxlZnRfam9pbihhY3RfYmVuICU+JSBzZWxlY3QoY2x1c3RlcjIgPSBzZWN0b3IsIFYyID0gY2F0ZWdvcmlhKSAlPiUgZGlzdGluY3QoKSwgYnkgPSAiVjIiKSAlPiUgDQogIG11dGF0ZShtdWx0aWNsdXN0ZXIgPSBpZmVsc2UoY2x1c3RlcjEgIT0gY2x1c3RlcjIsIDEsIDApLA0KICAgICAgICAgY29tYmluYXRpb24gPSBwYXN0ZTAoVjEsIiAvICIsIFYyKSkgJT4lDQogIGZpbHRlcihtdWx0aWNsdXN0ZXIgPT0gMSkgJT4lIA0KICBzZWxlY3QoY29tYmluYXRpb24sIGNvdW50KSAlPiUNCiAgbXV0YXRlKGNvbWJpbmF0aW9uID1zdHJfdG9fdGl0bGUoY29tYmluYXRpb24pKSAlPiUgDQogIGRpc3RpbmN0KCkgJT4lIA0KICBhcnJhbmdlKGRlc2MoY291bnQpKSAlPiUgDQogIGhlYWQoMTUpICU+JSANCiAgcGFuZGVyKGNhcHRpb24gPSAiTW9zdCBjb21tb24gaW50ZXItY2x1c3RlciBhY3Rpdml0eSBjYXRlZ29yeSBjb21iaW5hdGlvbnMiLCBzdHlsZSA9ICJybWFya2Rvd24iLCAgDQogICAgICAgICBqdXN0aWZ5ID0gYygibGVmdCIsICJyaWdodCIpKQ0KYGBgDQoNCk9mIHRoZSAxNSBtb3N0IGNvbW1vbiBhY3Rpdml0eSBjYXRlZ29yeSBjb21iaW5hdGlvbnMsIHdlIHNlZSBmb3VyIGNvbWJpbmF0aW9ucyB3aGljaCBhY3R1YWxseSBjb252ZXkgbXVsdGktc2VjdG9yIGJlbmVmaXRzOiANCg0KKiBUaGUgNHRoIGFuZCAxMXRoIGVudHJpZXMsIF9QcmV2ZW50aW9uIG9mIGFjdXRlIG1hbG51dHJpdGlvbiAvIFByb3Zpc2lvbiBvZiBwcm90ZWN0aW9uIHNlcnZpY2VzXyBhbmQgX1Byb3Zpc2lvbiBvZiBwcm90ZWN0aW9uIHNlcnZpY2VzIC8gVHJlYXRtZW50IG9mIGFjdXRlIG1hbG51dHJpdGlvbl8gd2hlcmUgcmVmZXJyYWxzIGJldHdlZW4gdGhlIE51dHJpdGlvbiBhbmQgUHJvdGVjdGlvbiBjbHVzdGVycyBtaWdodCBmZWFzaWJseSByZXN1bHQgaW4gdnVsbmVyYWJsZSBwb3B1bGF0aW9ucyByZWNlaXZpbmcgYSBjb21iaW5hdGlvbiBvZiBwcm90ZWN0aW9uIHNlcnZpY2VzLCBtaWNyb251dHJpZW50IHN1cHBsZW1lbnRhdGlvbiwgZGUtd29ybWluZywgdHJlYXRtZW50IGFuZCBjb3Vuc2VsbGluZyB0aGF0IHdvdWxkIHJlZHVjZSB0aGVpciB2dWxuZXJhYmlsaXR5IGluIGEgbXVsdGlkaW1lbnNpb25hbCBtYW5uZXI7IHRoZQ0KKiA5dGggZW50cnksIF9XYXRlciBzdXBwbHkgaW4gY29tbXVuaXRpZXMgLyBQcmV2ZW50aW9uIG9mIGFjdXRlIG1hbG51dHJpdGlvbl8sIGFzIGltcHJvdmVkIHdhdGVyIHN1cHBseSBpcyBhIGNvcmUgY29tcG9uZW50IG9mIHByZXZlbnRpbmcgbWFsbnV0cml0aW9uOyBhbmQgdGhlDQoqIDExdGgsIF9BY2Nlc3MgdG8gZWR1Y2F0aW9uIGFuZCBzdHVkZW50IHJldGVudGlvbiAvIFByb3Zpc2lvbiBvZiBwcm90ZWN0aW9uIHNlcnZpY2VzXywgYXMgdGhlIHBvcHVsYXRpb24gb2YgY2hpbGRyZW4gd2l0aCBwb29yIGFjY2VzcyB0byBlZHVjYXRpb24gYW5kIGFyZSBpbiBkYW5nZXIgb2YgZHJvcHBpbmcgb3V0IHdvdWxkLCBwcmVzdW1hYmx5LCBiZSBtb3JlIGluIG5lZWQgb2YgcHJvdGVjdGlvbiBzZXJ2aWNlcyAod2hpY2ggaW5jbHVkZSByZWZlcnJhbHMgdG8gdGhlIGZvcm1hbCBzb2NpYWwgd2VsZmFyZSBzeXN0ZW0sIGxlZ2FsIGFpZCwgc3VwcG9ydCBmb3IgR0JWIHN1cnZpdm9ycyBhbmQgVUFTQykuIA0KDQpIb3dldmVyLCBhcyBtZW50aW9uZWQgcHJldmlvdXNseSwgdGhlc2UgbXVsdGktc2VjdG9yIGJlbmVmaXRzIGFyZSB0aGVvcmV0aWNhbCBhbmQgaXQgaGFzIG5vdCBiZWVuIGVzdGFibGlzaGVkIHRoYXQgdGhlcmUgaXMgY29tbXVuaWNhdGlvbiBiZXR3ZWVuIHRoZSBpbXBsZW1lbnRpbmcgcGFydG5lcnMgb2YgdGhlc2UgYWN0aXZpdGllcy4gUHJvamVjdCBtb25pdG9yaW5nIGlzIHJlcXVpcmVkIHRvIGVzdGFibGlzaCB0aGlzLiANCg0KQ29tYmluYXRpb25zIGxpa2UgX0FjY2VzcyB0byBlZHVjYXRpb24gYW5kIHN0dWRlbnQgcmV0ZW50aW9uIC8gUHJldmVudGlvbiBvZiBhY3V0ZSBtYWxudXRyaXRpb25fKDFzdCkgZGVhbCB3aXRoIGFsbW9zdCBlbnRpcmVseSBzZXBhcmF0ZSBwb3B1bGF0aW9ucyAtLSBjaGlsZHJlbiBvZiBzY2hvb2xnb2luZyBhZ2UgYXJlIG91dHNpZGUgb2YgdGhlIHRhcmdldCBwb3B1bGF0aW9uIGZvciBOdXRyaXRpb247IHRob3VnaCBpdCBpcyBmZWFzaWJsZSB0aGF0IEVkdWNhdGlvbiBhbmQgTnV0cml0aW9uIG1pZ2h0IGJvdGggYmUgZGVhbGluZyB3aXRoIHRoZSBzYW1lIHlvdW5nIG1vdGhlciB3aG8gaGFzIGRyb3BwZWQgb3V0IG9mIHNjaG9vbC4gDQoNCkZ1cnRoZXJtb3JlLCBjb21iaW5hdGlvbnMgbGlrZSBfUHJldmVudGlvbiBvZiBhY3V0ZSBtYWxudXRyaXRpb24gLyBSZXNpbGllbmNlIGluIGVkdWNhdGlvbl8oMm5kKSBhbmQgX0NhcGFjaXR5IGJ1aWxkaW5nIGluIGVkdWNhdGlvbiAvIFByZXZlbnRpb24gb2YgYWN1dGUgbWFsbnV0cml0aW9uXygzcmQpIGhhdmUgbm8gb3ZlcmxhcCBhcyBtYWxudXRyaXRpb24gcHJldmVudGlvbiBoYXMgbm8gcHJvZ3JhbW1hdGljIGxpbmsgdG8gc2FmZSBzY2hvb2wgc3RyYXRlZ2llcywgRFJSIGluIHNjaG9vbHMgYW5kIHRlYWNoZXIgdHJhaW5pbmcuDQoNCkFzIGl0IHN0YW5kcywgY2x1c3RlciBmb290cHJpbnRzIHNlZW0gdG8gaGF2ZSBtdWNoIG1vcmUgdG8gZG8gd2l0aCBvcHBvcnR1bmlzdGljIGV4cGFuc2lvbiBzdHJhdGVnaWVzIGRlcGVuZGVudCBvbiBpbXBsZW1lbnRpbmcgcGFydG5lciBjYXBhY2l0aWVzIGFuZCB3aGVyZSB0aGV5IGhhdmUgbmVnb3RpYXRlZCBhY2Nlc3Mgd2l0aCBsb2NhbCBnb3Zlcm5tZW50cyB0aGFuIGEgbmVlZHMtYmFzZWQgYXBwcm9hY2ggd2hpY2ggdGFyZ2V0cyB0aGUgbW9zdCB2dWxuZXJhYmxlLiBUaGUgbmV4dCBwYXJ0IGlzIGFuIGVmZm9ydCB0byBleGFtaW5lIGFuZCBjb3JyZWN0IHRoaXMuIA0KDQo8YnI+DQoNCiMjIDUuIERlY2lzaW9uIHRyZWVzDQoNCiMjIyA1YS4gSW50cm9kdWN0aW9uIHRvIHRyZWVzIC0tIG9yZ2FzYXRpb25hbCBwcmVzZW5jZQ0KDQpUbyBwcmlvcml0aXNlIGJldHdlZW4gdGhlIGByIG5yb3cocGFycilgIHBhcnJpc2hlcyBpbiBWZW5lenVlbGEgLS0gdGhhdCBpcywgdG8gZGV0ZXJtaW5lIHdoZXJlIHdlIHNob3VsZCBiZSB3b3JraW5nIC0tIGl0IGlzIG5lY2Vzc2FyeSB0byBzcGxpdCB0aGVtIHVwIGludG8gbW9yZSBlYXNpbHkgZGlnZXN0aWJsZSBncm91cHMsIGFuZCB3ZSB3aWxsIHVzZSBkZWNpc2lvbiB0cmVlcyB0byBkbyB0aGlzLiBBIHByaW9yaXRpc2F0aW9uIG9yIHZ1bG5lcmFiaWxpdHkgc2NvcmUgaXMgYW5vdGhlciBjb21tb25seS11c2VkIHByaW9yaXRpc2F0aW9uIHRvb2wsIGJ1dCwgYXMgd2Ugd2lsbCBzZWUsIGNvbGxhcHNpbmcgYSBudW1iZXIgb2YgdmFyaWFibGVzIGRvd24gaW50byBvbmUgc2NvcmUgaXMgbm90IGFsd2F5cyBoZWxwZnVsLiANCg0KVG8gdW5kZXJzdGFuZCBob3cgYSBkZWNpc2lvbiB0cmVlIGZ1bmN0aW9ucywgbGV0IHVzIGNvbnN0cnVjdCBvbmUgdG8gcHJlZGljdCB3aGV0aGVyIG9yIG5vdCB0aGVyZSBpcyBhIGh1bWFuaXRhcmlhbiBhZ2VuY3kgcHJlc2VudCBpbiBhIHBhcnJpc2ggKGBvcmdfcHJlc2VudGAgLS0gdGhpcyBpcyBvdXIgZGVwZW5kZW50IHZhcmlhYmxlKS4gV2UgaGF2ZSBzdXBwbGllZCBvdXIgbW9kZWwgd2l0aCBhIGJhc2tldCBvZiBjZW5zdXMgaW5kaWNhdG9ycyBmcm9tIHdoaWNoIGl0IHdpbGwgY29uc3RydWN0IGEgdHJlZSB0byBwcmVkaWN0IG91ciAtLSB1bmhpZGUgdGhlIGNvZGUgYmVsb3cgdG8gc2VlIHRoZSBmdWxsIG1vZGVsLiBUaGUgZGVjaXNpb24gdHJlZSBwcmludGVkIGJlbG93IGlzIHRoZSByZXN1bHQ6IA0KDQpgYGB7ciB0cmVlMn0NCiMganVzdCB0byBzaG93IHRoZSBkZWNpc2lvbiB0cmVlIG9mIGhvdyBwYXJ0bmVycyBzZWVtIHRvIGhhdmUgY2hvc2VuIGxvY2F0aW9ucy4gDQojIHVzaW5nIGZ1bGwgcGFyciBkYXRhc2V0IGZvciB0aGUgdHJlZQ0KIyBubyBkb3VidCB0aGVyZSBhcmUgb3RoZXIgZmFjdG9ycywgYnV0IHRoaXMgaXMgdGhlIGRhdGEgSSBoYXZlIC0tIA0KIyBsb29raW5nIGF0IHNwZWNpZmljIHBhcnRuZXIgY2hhcmFjdGVyaXN0aWNzIHdvdWxkIGJlIGludGVyZXN0aW5nLiANCnNldC5zZWVkKDMwMDApDQoNCnRyZWUyIDwtIHBhcnIgJT4lIA0KICBycGFydChvcmdfcHJlc2VudCB+IHBlcmNlbnRfcG9icmUgKyBwZXJjZW50X3VyYmFuYSArIGRlbnNpZGFkX3BwbF9rbTIgKyANCiAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfZGVfbWVub3Jlc19kZV8xNV9hbm9zICsgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQogICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhICsgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKw0KICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIA0KICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsIGRhdGEgPSAuLCBtaW5idWNrZXQgPSAxMDApDQoNCmZhbmN5UnBhcnRQbG90KHRyZWUyLCBkaWdpdHMgPSAtMywgc3ViID0gIiIsIHBhbGV0dGVzID0gIkJsdWVzIiwgdHlwZSA9IDIpDQpgYGANCg0KVG8gdW5kZXJzdGFuZCB0aGUgcGxvdCBhYm92ZSwgYWxsIHBhcnJpc2hlcyBoYXZlIGJlZW4gc3BsaXQgaW50byBmb3VyIGdyb3VwcyAodGhlIHRlcm1pbmFsIG5vZGVzIGF0IHRoZSBib3R0b20gbWFya2VkIFs0XSwgWzVdLCBbNl0gYW5kIFs3XSkgYmFzZWQgb24gdGhlIHBlcmNlbnRhZ2Ugb2YgcGFycmlzaGVzIGluIGVhY2ggbm9kZSB3aGVyZSBodW1hbml0YXJpYW4gYWdlbmNpZXMgYXJlIHByZXNlbnQuIEVhY2ggbm9kZSBoYXMgdGhyZWUgZmlndXJlcyAtLSBmb3IgaW5zdGFuY2UsIHRoZSByb290LCBhdCB0aGUgdG9wLCBhbmQgbWFya2VkIFsxXSwgc2hvd3MgdGhhdCBvbiBhdmVyYWdlLCAwLjUyNCBvciA1Mi40JSBvZiBhbGwgcGFycmlzaGVzIGhhdmUgaHVtYW5pdGFyaWFuIGFnZW5jaWVzIHByZXNlbnQgaW4gdGhlbS4gVGhlIG5leHQgbnVtYmVycywgIm4gPSAxMTA5IiBzaG93cyB0aGF0IGByIG5yb3cocGFycilgIHBhcnJpc2hlcyBhcmUgaW4gdGhhdCBncm91cCBhbmQgbmV4dCB0byBpdCBpcyB0aGUgcGVyY2VudGFnZSBvZiBwYXJyaXNoZXMgaXQgY29udGFpbnMsIHdoaWNoLCBzaW5jZSBpdCBpcyB0aGUgcm9vdCwgaXMgMTAwJS4gDQoNCldlIHNlZSB0aGF0IFs3XSAoaW4gZGFyayBibHVlKSB0aGUgbm9kZSB3aXRoIHRoZSBoaWdoZXN0IGNvbmNlbnRyYXRpb24gb2YgcGFycmlzaGVzIHdpdGggYWdlbmNpZXMgcHJlc2VudCAoODIuOCUpLCBjb25zaXN0cyBvZiBwYXJyaXNoZXMgbW9yZSB0aGFuIDc5LjQlIHVyYmFuaXNlZCBhbmQgZGVuc2VyIHRoYW4gMTg3IHBwbC9rbTIuIEFuZCBbNF0sIHRoZSBub2RlIHdpdGggdGhlIGxvd2VzdCBjb25jZW50cmF0aW9uIG9mIHBhcnJpc2hlcyB3aXRoIGFnZW5jaWVzICgyMi42JSkgaXMgbGVzcyB0aGFuIDc5LjQlIHVyYmFuaXNlZCBfYW5kXyBsZXNzIHRoYW4gMjEuOCUgdXJiYW5pc2VkLiANCg0KVGhpcyBpcywgb2YgY291cnNlLCBub3QgdG8gaW1wbHkgdGhhdCB0aGlzIGFjdHVhbGx5IGRlcGljdHMgcGFydG5lcnMnIGRlY2lzaW9uLW1ha2luZyBwcm9jZXNzLCBqdXN0IHRoYXQgdGhlc2UgYXJlIHRoZSBmYWN0b3JzIHRvd2FyZHMgd2hpY2ggd2UsIGFzIGEgcmVzcG9uc2UsIGFyZSBwcmVkaXNwb3NlZC4gUGVyaGFwcyBpdCBpcyB1bmRlcnN0YW5kYWJsZSB0aGF0IHRoZSBtb3N0IGhlYXZpbHkgcG9wdWxhdGVkIHBhcnJpc2hlcyBhcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSBvcmdhbmlzYXRpb25zIHByZXNlbnQsIHRob3VnaCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHVyYmFuIHBvcHVsYXRpb24gYXJlIGJvdGggbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggcG92ZXJ0eSBpbmNpZGVuY2UuIFRoZSBsYXJnZXN0IGRldGVybWluYW50cyBvZiB0aGUgX251bWJlcl8gb2YgYmVuZWZpY2lhcmllcyByZWFjaGVkIHBlciBwYXJyaXNoIGFyZSBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHVyYmFuaXNhdGlvbiwgYXMgYmVuZWZpY2lhcnkgbnVtYmVycyB0ZW5kIHRvIHNjYWxlIGluIGxpbmUgd2l0aCBsYXJnZXIgcG9wdWxhdGlvbnMuIA0KDQo8YnI+DQoNCiMjIyA1Yi4gUHJpb3JpdGlzYXRpb24gdHJlZXMNCg0KTm93IGxldCB1cyBzdGFydCBvbiB3aGVyZSB0byBnbyBmcm9tIGhlcmU6IA0KDQpTZXZlcmFsIHRyZWVzIHdlcmUgYnVpbHQgYW5kIHRyaWFsbGVkIHRvIHNwbGl0IHBhcnJpc2hlcyBpbnRvIHRhcmdldHRpbmcgZ3JvdXBzLiBBcyBtZW50aW9uZWQsIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgY29tZSBmcm9tIGEgcG9vbCBvZiBpbmRpY2F0b3JzIGZyb20gdGhlIGNlbnN1cyBkYXRhc2V0LCB3aXRoIHNvbWUgb3JpZ2luYXRpbmcgZnJvbSB0aGUgMjAxOSBVTklDRUYgTXVuaWNpcGFsIFByaW9yaXRpc2F0aW9uIFRvb2wsIHdoaWNoIHdhcyBhIFByaW5jaXBhbCBDb21wb25lbnRzIEFuYWx5c2lzIG9mIGtleSB2YXJpYWJsZXMgcmVsYXRlZCB0byBwb3ZlcnR5LCBoZWFsdGggYW5kIG1vcnRhbGl0eSBhbmQgdmlvbGVuY2UgYW5kIGluc2VjdXJpdHkuIEFmdGVyIG51bWVyb3VzIGl0ZXJhdGlvbnMsICoqYHRyZWUzYCoqIHdhcyBjaG9zZW4gYW5kIGl0IHNwbGl0cyBwYXJyaXNoZXMgaW50byBncm91cHMgYWNjb3JkaW5nIHRvIHRoZTogIA0KDQoqIFRoZSBwb3ZlcnR5IHNjb3JlLCB3aGljaCBpcyB0aGUgYSByZXNjYWxlZCBhdmVyYWdlIG9mIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zIGFuZCB0aGUgcG92ZXJ0eSBpbmNpZGVuY2Ugb2YgZWFjaCBwYXJyaXNoLiANCiAgDQpUbyBzZWUgdGhlIHNwZWNpZmljIHZhcmlhYmxlcyBhbmQgZm9ybXVsYWUgdXNlZCBmb3IgZWFjaCBvZiB0aGUgbWFqb3IgaXRlcmF0aW9ucywgYXMgd2VsbCBhcyBhZGRpdGlvbmFsIG5vdGVzIG9uIHRoZSBkZXZlbG9wbWVudCBhbmQgYXBwbGljYXRpb24gb2YgZGVjaXNpb24gdHJlZXMsIHVuaGlkZSB0aGUgc291cmNlIGNvZGUgYmVsb3cuIA0KDQpgYGB7ciB0cmVlcy1SRUYtd3JpdGUtaW50by1wYXJyMH0NCiANCiMgQXMgb3Bwb3NlZCB0byBhIHByaW9yaXRpc2F0aW9uIHNjb3JlIC0tIHR5cGljYWxseSB0aGUgd2VpZ2h0ZWQgYXZlcmFnZSBvZiBzZXZlcmFsIGRlbW9ncmFwaGljIGFuZCBzb2Npb2Vjb25vbWljIGluZGljYXRvcnMgLS0gYSB0cmVlIGlzIG11Y2ggYmV0dGVyIGF0IGFjY291bnRpbmcgZm9yIHRoZSB2YXJpYXRpb25zIGFjcm9zcyBnZW9ncmFwaGljIGFyZWFzLiBBIHBhcnRuZXIgbWlnaHQgbm90IGhhdmUgdGhlIGNhcGFjaXR5IHRvIHdvcmsgb3V0c2lkZSBvZiB1cmJhbiBhcmVhcyBvciBhbm90aGVyIG1pZ2h0IGhhdmUgc3BlY2lmaWMgZ2VvZ3JhcGhpYyBiaWFzZXMgYW5kIGRlY2lzaW9uIHRyZWVzIGFyZSBhIGdvb2QgdG9vbCB0byBtYWtlIHRoZSBiZXN0IHBvc3NpYmxlIHRhcmdldHRpbmcgZGVjaXNpb25zIHdpdGhpbiBvbmUncyBjb25zdHJhaW50cy4gIA0KDQojIFdpdGggdGhhdCBpbiBtaW5kLCB0cmVlMyB3YXMgZGV2ZWxvcGVkIHRvIGFpZCBmdXR1cmUgcHJpb3JpdGlzYXRpb24uIFRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZSBpdCBzdHJpdmVzIHRvIHByZWRpY3QgaXMgdGhlIHBvdmVydHkgc2NvcmUsIHdoaWNoLCBhcyBtZW50aW9uZWQsIGlzIGp1c3QgdGhlIHJlc2NhbGVkIGF2ZXJhZ2Ugb2YgbnVtYmVyIG9mIHBvb3IgcGVyc29ucyBhbmQgcG92ZXJ0eSBpbmNpZGVuY2UuIFRoZSBwZXJmb3JtYW5jZSBvZiB0cmVlMyB3YXMgY29uc2lkZXJlZCBzdXBlcmlvciB0byBib3RoIHRyZWUxICh3aG9zZSBpbmRlbmRlcGVudCB2YXJpYWJsZSBpcyBqdXN0IHRoZSBhYnNvbHV0ZSBudW1iZXIgb2YgcG9vciBwZXJzb25zKSBhbmQgdHJlZTQgKHdoaWNoIGNvbnNpZGVyZWQgcGFycmlzaC1sZXZlbCBnYXBzKSBkdWUgdG8gaXRzIGFiaWxpdHkgY2xlYXJseSBkaXN0aW5ndWlzaCBpdHMgZ3JvdXBzIG9mIHBhcnJpc2hlcyBhbmQgYmVjYXVzZSBpdCBpcyBub3QgZGVwZW5kZW50IG9uIGdhcHMgZGF0YSAtLSBtZWFuaW5nIGl0IHdpbGwgbm90IHNoaWZ0IHdoZW4gdGhlIDVXcyBhcmUgdXBkYXRlZC4NCg0Kc2V0LnNlZWQoMzAwMCkNCg0KIyBudW1iZXIgb2Ygbm90IGNvdmVyZWQgcG9vciBwZXJzb25zIA0KdHJlZTEgPC0gcGFycjAgJT4lDQogIHJwYXJ0KG5vdF9yZWFjaGVkIH4gZXN0YWRvICsgcGVyY2VudF9wb2JyZSArIHBlcmNlbnRfdXJiYW5hICsgDQogICAgICAgIGRlbnNpZGFkX3BwbF9rbTIgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyANCiAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQogICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhICsgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKw0KICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIA0KICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsIGRhdGEgPSAuLCBjcCA9IDAuMDM4KQ0KDQojIHRyZWUgYmFzZWQgb24gcG92ZXJ0eV9zY29yZQ0KdHJlZTMgPC0gcGFycjAgJT4lDQogIHJwYXJ0KHBvdmVydHlfc2NvcmUgfiBlc3RhZG8gKyBwZXJjZW50X3VyYmFuYSArIGRlbnNpZGFkX3BwbF9rbTIgKw0KICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQogICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyArIHBlcmNlbnRfYW5hbGZhYmV0byArIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSwNCiAgICAgICAgcHJvbWVkaW9fZGVfcGVyc29uYXNfcG9yX3ZpdmllbmRhLCBkYXRhID0gLiwgY3AgPSAwLjA0NCkNCg0KIyB0cmVlIGJhc2VkIG9uIGdhcCBzY29yZSAtLSBsZXQncyBub3QgdXNlIHRoaXMgYXMgdHJlZTMgaXMgbW9yZSBzdGFibGUgYW5kIHdpbGwgbm90IGNoYW5nZSBiYXNlZCBvbiBuZXcgNVcgZGF0YSANCiMgdHJlZTQgPC0gcGFycjAgJT4lDQojICAgcnBhcnQoZ2FwX3Njb3JlIH4gZXN0YWRvICsgcGVyY2VudF91cmJhbmEgKyBkZW5zaWRhZF9wcGxfa20yICsNCiMgICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiMgICAgICAgICBwZXJjZW50X3Npbl9hZ3VhX3NlZ3VyYSArIHBlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvICsNCiMgICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIA0KIyAgICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwgZGF0YSA9IC4sIGNwID0gMC4wNDUpDQoNCiMgcGxvdGNwKHRyZWUzKQ0KIyBwcmludGNwKHRyZWUzKQ0KDQojIGFkZGluZyB0cmVlMSBhbmQgdHJlZTMgcnVsZXMgdG8gdGhlIGRhdGFzZXQgDQpwYXJyMCA8LSBwYXJyMCAlPiUgDQogIG11dGF0ZShydWxlMSA9IHJvdy5uYW1lcyh0cmVlMSRmcmFtZSlbdHJlZTEkd2hlcmVdKSAlPiUNCiAgICAgIGxlZnRfam9pbihycGFydC5ydWxlcy50YWJsZSh0cmVlMSkgJT4lIA0KICAgICAgZmlsdGVyKExlYWYgPT0gVFJVRSkgJT4lIA0KICAgICAgcmVuYW1lKHJ1bGUxID0gUnVsZSkgJT4lIA0KICAgICAgZ3JvdXBfYnkocnVsZTEpICU+JSANCiAgICAgIHN1bW1hcmlzZShzdWJydWxlczEgPSBwYXN0ZShTdWJydWxlLCBjb2xsYXBzZSA9ICIsIikpKSAgJT4lIA0KICBtdXRhdGUocnVsZTMgPSByb3cubmFtZXModHJlZTMkZnJhbWUpW3RyZWUzJHdoZXJlXSkgJT4lDQogICAgICBsZWZ0X2pvaW4ocnBhcnQucnVsZXMudGFibGUodHJlZTMpICU+JSANCiAgICAgIGZpbHRlcihMZWFmID09IFRSVUUpICU+JSANCiAgICAgIHJlbmFtZShydWxlMyA9IFJ1bGUpICU+JSANCiAgICAgIGdyb3VwX2J5KHJ1bGUzKSAlPiUgDQogICAgICBzdW1tYXJpc2Uoc3VicnVsZXMzID0gcGFzdGUoU3VicnVsZSwgY29sbGFwc2UgPSAiLCIpKSkNCg0KYGBgDQoNCjxicj4NCg0KIyMjIDVjLiBTdWItZ3JvdXBzIG9mIGRlY2lzaW9uIHRyZWUzDQoNCkJlbG93IGlzIGEgcGxvdCBvZiAqKmB0cmVlM2AqKiAtLSB0aGUgYHIgbnJvdyhwYXJyMClgIHBhcnJpc2hlcyB3aGVyZSB0aGUgbnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgZG9lcyBub3QgZXhjZWVkIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zIChjb3JyZXNwb25kaW5nIHRvIHRoZSBfdW5kZXJfIGFuZCBfbm8gY292ZXJhZ2VfIGNhdGVnb3JpZXMpIGhhdmUgYmVlbiBzcGxpdCBpbnRvIGZvdXIgdGVybWluYWwgbm9kZXM6IFs0XSwgWzVdLCBbNl0gYW5kIFs3XS4gVGhlIG1hbm5lciBpbiB3aGljaCB0aGV5IGhhdmUgYmVlbiBzcGxpdCBpcyBtZWFuaW5nZnVsIGZvciB0YXJnZXR0aW5nIGRlY2lzaW9ucyBhbmQgdGhpcyBzZWN0aW9uIHdpbGwgY29tcGFyZSB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIGVhY2guIFBsZWFzZSBub3RlIHRoYXQgdGhpcyBpcyBhIGRpZmZlcmVudCB0cmVlIHRoYW4gaW4gc2VjdGlvbiA1YSAtLSB0aGUgdGVybWluYWwgbm9kZXMgaGF2ZSB0aGUgc2FtZSBudW1iZXJpbmcganVzdCBiZWNhdXNlIHRoZSB0d28gbW9kZWxzIGhhdmUgdGhlIHNhbWUgbnVtYmVyIG9mIHJ1bGVzLg0KDQpgYGB7ciB0cmVlMy1ycGFydFBsb3R9DQoNCmZhbmN5UnBhcnRQbG90KHRyZWUzLCBkaWdpdHMgPSAtMywgc3ViID0gIiIsIHBhbGV0dGVzID0gIkJsdWVzIiwgdHlwZSA9IDIpDQpgYGANCiANCjxicj4NCiANCiMjIyMgU3VtbWFyeSBhbmQgb3ZlcnZpZXcgb2YgdGhlIHRlcm1pbmFsIG5vZGVzIG9mIHRyZWUzIA0KDQpgYGB7ciB0cmVlMy1ydWxlcy1UQUJMRX0NCiMgd2lsbCB0aGV5IGJlIGNvbmZ1c2VkIHRoYXQgdGhlIHRlcm1pbmFsIG5vZGVzIGhhdmUgdGhlIHNhbWUgY29kZXM/IFNob3VsZCBJIGV4cGxhaW4gaW4gdGhlIHRleHQgdGhhdCB0aGlzIGlzIGJlY2F1c2UgdGhleSBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiBydWxlcyBvciB3aWxsIHRoYXQganVzdCBtYWtlIHRoZW0gbW9yZSBjb25mdXNlZD8gDQoNCnBhcnIwICU+JSANCiAgZ3JvdXBfYnkocnVsZTMpICU+JSANCiAgc3VtbWFyaXNlKHBhcnJfbm9fYmVuID0gbl9kaXN0aW5jdChwY29kZTNbYmVuZWZpY2lhcmlvcyA9PSAwXSksDQogICAgICAgICAgICBiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgICAgYXZnX2JlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBuKCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSBzdW0obm90X3JlYWNoZWQpLA0KICAgICAgICAgICAgYXZnX25vdF9yZWFjaGVkID0gc3VtKG5vdF9yZWFjaGVkKSAvIG4oKSwNCiAgICAgICAgICAgIGF2Z19vcmdfY291bnQgPSBtZWFuKG9yZ19jb3VudCksDQogICAgICAgICAgICBhdmdfcG9ibGFjaW9uID0gbWVhbihwb2JsYWNpb25fMjAxOSksDQogICAgICAgICAgICBwZXJjZW50X3BvYnJlID0gcm91bmQoc3VtKHBvYl9wb2JyZSkgLyBzdW0ocG9ibGFjaW9uXzIwMTkpLCBkaWdpdHMgPSAyKSwNCiAgICAgICAgICAgIHBlcmNlbnRfdXJiYW5hID0gcm91bmQoc3VtKHBvYl91cmJhbmEpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwgZGlnaXRzID0gMiksDQogICAgICAgICAgICBkZW5zaWRhZF9wcGxfa20yID0gc3VtKHBvYmxhY2lvbl8yMDE5KSAvIHN1bShhcmVhX2ttMiwgbmEucm0gPSBUUlVFKSwNCiAgICAgICAgICAgIHBhcnJvcXVpYXMgPSBuKCkpICU+JSANCiAgZ2F0aGVyKGtleSA9IHZhcmlhYmxlLCB2YWx1ZSA9IHZhbHVlLCAyOm5jb2woLikpICU+JSANCiAgc3ByZWFkXyhrZXkgPSBuYW1lcyguKVsxXSwgdmFsdWUgPSAndmFsdWUnKSAlPiUgDQogICMgcmVvcmRlcmluZyB0aGUgdGFibGUgaW5zdGVhZCBvZiBoYXZpbmcgaXQgYmUgYWxwaGFiZXRpY2FsDQogIGFycmFuZ2UoZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJub3RfcmVhY2hlZCIsICJhdmdfbm90X3JlYWNoZWQiLCAiYXZnX3BvYmxhY2lvbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmVuZWZpY2lhcmlvcyIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJhdmdfYmVuZWZpY2lhcmlvcyIsICAiYXZnX29yZ19jb3VudCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwZXJjZW50X3BvYnJlIiwgInBlcmNlbnRfdXJiYW5hIiwgImRlbnNpZGFkX3BwbF9rbTIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBhcnJvcXVpYXMiLCAicGFycl9ub19iZW4iKSkpICU+JSAgDQogIA0KICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIpDQoNCmBgYA0KDQoqIFs0XSBjb25zaXN0cyBvZiBwb3B1bGF0aW9uIGNlbnRyZXMgd2hpY2ggYXJlIGVhc3kgdG8gcmVhY2gsIGJ1dCB3aXRoIG9ubHkgMjEuOCUgb2YgdGhlIHBvcHVsYXRpb24gYmVpbmcgcG9vciwgY2FyZWZ1bCB0YXJnZXR0aW5nIGFuZCBiZW5lZmljaWFyeSBzZWxlY3Rpb24gaXMgcmVxdWlyZWQgLS0gYmxhbmtldCBjb3ZlcmFnZSB3aWxsIG9ubHkgcmVzdWx0IGluIGV4Y2Vzc2l2ZSBpbmNsdXNpb24gZXJyb3JzLiBJdCBhbHNvIGhhcyB0aGUgaGlnaGVzdCBhdmVyYWdlIG51bWJlciBvZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgcGVyIHBhcnJpc2ggKGF2Z19vcmdfY291bnQpLiBUaGVyZSBhcmUgYHIgZmlsdGVyKHBhcnIwLCBydWxlMyA9PSAiNCIpICU+JSBucm93KClgIHBhcnJpc2hlcyBpbiB0aGlzIGdyb3VwLiBUaGVzZSBwYXJyaXNoZXMgc2hvdWxkIG5vdCBiZSBwcmlvcml0aXNlZCAtLSByZXNvdXJjZXMgc2hvdWxkIGJlIGFsbG9jYXRlZCBlbHNld2hlcmUuIA0KDQoqIFs1XSBpcyBwcm9iYWJseSB0aGUgYmVzdCBvcHRpb24gZm9yIGV4cGFuc2lvbiBmb3IgbW9zdCBwYXJ0bmVycyAtLSBpdCBoYXMgdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgcGVyIHBhcnJpc2ggKG5jX3Blcl9wYXJyKSwgaXMgc3Vic3RhbnRpYWxseSBwb29yZXIgdGhhbiBbNF0sIHdpdGggYSBwb3ZlcnR5IGluY2lkZW5jZSBvZiAzOCUuIEFkZGl0aW9uYWxseSwgdGhlc2UgcGFycmlzaGVzIGFyZSBzdGlsbCB2ZXJ5IHVyYmFuaXNlZCAoOTIuNSUpLCBtZWFuaW5nIHRoYXQgYWNjZXNzIHRvIHRoZXNlIHBvcHVsYXRpb25zIHdpbGwgbm90IGJlIGNoYWxsZW5naW5nLiBUaGUgY292ZXJhZ2Ugb2Ygb3JnYW5pc2F0aW9ucyBpcyBzdGlsbCBmYWlybHkgaGlnaCBhbmQgcGFydG5lcnMgc2hvdWxkIGNvbnNpZGVyIGV4cGFuZGluZyBpbnRvIHBhcnJpc2hlcyB0byB0aGUgb25lcyB0aGV5IGN1cnJlbnRseSBjb3Zlci4gVGhpcyBpcyB0aGUgbGFyZ2VzdCBncm91cCwgd2l0aCBgciBmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI1IikgJT4lIG5yb3coKWAgcGFycmlzaGVzLiANCg0KKiBbNl0gaXMgd2hlcmUgYWNjZXNzIHN0YXJ0cyB0byBnZXQgbW9yZSBjaGFsbGVuZ2luZyAtLSB0aG91Z2ggdGhlc2UgcGFycmlzaGVzIGhhdmUgYW4gYXZlcmFnZSBwb3ZlcnR5IGluY2lkZW5jZSBvZiA1MiUsIHRoZSByYXRlIG9mIHVyYmFuaXNhdGlvbiBkcm9wcyB0byA3NSUgYW5kIHRoZSBwb3B1bGF0aW9uIGRlbnNpdHkgaXMgb25seSAxOCBwcGwva20yLiBCdXQgdGhlcmUgYXJlIHN0aWxsIG1vcmUgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkIHBlciBwYXJyaXNoIGluIHRoaXMgZ3JvdXAgdGhhbiBpbiBbNF0uIFRoZXJlIGFyZSBgciBmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI2IikgJT4lIG5yb3coKWAgcGFycmlzaGVzIGluIHRoaXMgZ3JvdXAuIA0KDQoqIFs3XSBjb25zaXN0cyBvZiB0aGUgcG9vcmVzdCwgbW9zdCB2dWxuZXJhYmxlIGFuZCBtb3N0IHJlbW90ZSBwYXJyaXNoZXMuIFdvcmtpbmcgaW4gdGhlc2UgYXJlYXMgd2lsbCBpbmN1ciBzaWduaWZpY2FudCBvcGVyYXRpb25hbCBhbmQgbG9naXN0aWNhbCBjb3N0cy4gSG93ZXZlciwgd2l0aCBhbiBhdmVyYWdlIHBvdmVydHkgaW5jaWRlbmNlIG9mIDc1LjIlLCBibGFua2V0IGNvdmVyYWdlIHdpbGwgYmUgd2FycmFudGVkIGluIG1hbnkgY2FzZXMgLS0gaWYgdGhlIGNoYWxsZW5nZSBvZiByZWFjaGluZyBhbGwgb2YgdGhlIHBvcHVsYXRpb24gY2FuIGJlIG1ldC4gQWRkaXRpb25hbGx5LCB0aGV5IGFsc28gaGF2ZSB0aGUgbG93ZXN0IGF2ZXJhZ2UgbnVtYmVyIG9mIHBvb3IgcGVyc29ucyBub3QgY292ZXJlZCwgZ2l2ZW4gdGhlaXIgZXh0cmVtZWx5IGxvdyBwb3B1bGF0aW9uIGRlbnNpdHkgb2YgMS44IHBwbC9rbTIuIEh1bWFuaXRhcmlhbiBhZ2VuY2llcyBoYXZlIHRoZSBsb3dlc3QgcHJlc2VuY2UgaW4gdGhlc2UgcGFycmlzaGVzLiBJdCBpcyBhZHZpc2FibGUgZm9yIGRvbm9ycyB0byBpbmNlbnRpdmlzZSBhY3Rpdml0aWVzIGluIHRoZXNlIGFyZWFzIGFzIGl0IGlzIGNsZWFyIHRoYXQgaHVtYW5pdGFyaWFuIGFnZW5jaWVzIGFyZSBhdm9pZGluZyB0aGVtLiBUaGVyZSBhcmUgYHIgZmlsdGVyKHBhcnIwLCBydWxlMyA9PSAiNyIpICU+JSBucm93KClgIHBhcnJpc2hlcyBpbiB0aGlzIGdyb3VwLg0KDQo8YnI+DQoNCiMjIyA1ZC4gTWFwcyBvZiBwYXJyaXNoZXMgYnkgZGVjaXNpb24gdHJlZSBub2RlDQoNCmBgYHtyIHRyZWUtMy1NQVAtb3JnLXByZXNlbnR9DQojIGp1c3Qgb25lIG5vdGUgZm9yIHRoaXMgbWFwIC0tIEkgc3RpbGwgY2FuJ3QgZmlndXJlIG91dCBob3cgdG8gZ2V0IHRoZSB0b29sdGlwIHRvIGFwcGVhciB3aGVuDQojIHlvdSdyZSBob3ZlcmluZyBvdmVyIHRoZSBjZW50cm9pZCBpbnN0ZWFkIG9mIGF0IHRoZSBib3JkZXI7IGhvdmVyb24gZmlsbCBkb2Vzbid0IHdvcmsuIA0KIyBJIHRoaW5rIHlvdSBzaG91bGQganVzdCBhc2sgc3RhY2tvdmVyZmxvdyBHSVMNCg0KIyBoZXggZm9yIFNldDIgIiM2NkMyQTUiLCAiI0ZDOEQ2MiIsICIjOERBMENCIiwgIiNFNzhBQzMiLCAiI0ZGRkZGRiINCiMgaGV4IGZvciBEYXJrMiAiIzFCOUU3NyIsICIjRDk1RjAyIiwgIiM3NTcwQjMiLCAiI0U3Mjk4QSIsICIjRkZGRkZGIg0KIyBoZXggZm9yIEFjY2VudCAiIzdGQzk3RiIsICIjQkVBRUQ0IiwgIiNGREMwODYiLCAiI0ZGRkY5OSIsICIjRkZGRkZGIg0KIyBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpDQojIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoKSkNCg0KcGFycm1hcF9vcmcgPC0gcGFyciAlPiUgDQogIGxlZnRfam9pbihwYXJyMCAlPiUgDQogICAgICAgICAgICAgIHNlbGVjdChwY29kZTMsIHJ1bGUzKSwgYnkgPSAicGNvZGUzIikgJT4lIA0KICByaWdodF9qb2luKHBjb2RlM19zaGFwZSwgYnkgPSAicGNvZGUzIikgJT4lIA0KICBzdF9hc19zZigpICU+JSANCiAgbXV0YXRlKG5vdF9yZWFjaGVkID0gcm91bmQobm90X3JlYWNoZWQsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgdHJlZV9ub2RlID0gcnVsZTMpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocGVyY2VudF9wb2JyZSwgcGVyY2VudF91cmJhbmEpLCB+KHJvdW5kKC4sIGRpZ2l0cyA9IDIpKSkgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2Yoc2l6ZSA9IDAuMSwgDQogICAgICAgICAgYWVzKGZpbGwgPSB0cmVlX25vZGUsDQogICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAocGFycm9xdWlhLCIsIiwgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdW5pY2lwaW8sICIsIiwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGFkbywgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAibm90IGNvdmVyZWQ6ICIsIG5vdF9yZWFjaGVkLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBvdmVydHkgaW5jaWRlbmNlOiAiLCBwZXJjZW50X3BvYnJlLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQgdXJiYW46ICIsIHBlcmNlbnRfdXJiYW5hLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIm9yZyBwcmVzZW50IDoiLCBvcmdfcHJlc2VudCksDQogICAgICAgICAgICAgYWxwaGEgPSBvcmdfcHJlc2VudCkpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY2QzJBNSIsICIjRkM4RDYyIiwgIiM4REEwQ0IiLCAiI0U3OEFDMyIpKSArDQogIHNjYWxlX2FscGhhX2Rpc2NyZXRlKHJhbmdlID0gYygxLCAwLjcpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSArDQogIGd1aWRlcyhhbHBoYSA9IEZBTFNFKSArDQogIGxhYnMoZmlsbCA9ICJUcmVlIG5vZGUiLA0KICAgICAgIGFscGhhID0gIiIpICsNCiAgZ2d0aXRsZSgnTWFwIG9mIHBhcnJpc2hlcyBieSBkZWNpc2lvbiB0cmVlIG5vZGUgKGNvbG91cikgJiBpZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgKGFscGhhKScpDQogIA0KZ2dwbG90bHkocGFycm1hcF9vcmcsIHRvb2x0aXAgPSBjKCJ0ZXh0IiwgImZpbGwiKSkgJT4lDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgNCiAgICAiTWFwIG9mIHBhcnJpc2hlcyBieSBkZWNpc2lvbiB0cmVlIG5vZGUgKGNvbG91cikgJiBpZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgKGFscGhhKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPHN1cD4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb3VzZSBvdmVyIGZvciBkZXRhaWxzOyBkcmFnIGFuZCBjbGljayB0byBzZWxlY3QgYW5kIHpvb207IGRvdWJsZS1jbGljayBsZWdlbmQgc2VsZWN0L2Rlc2VsZWN0IiwiPC9zdXA+IikpKQ0KDQoNCmBgYA0KDQpBYm92ZSBpcyBhIG1hcCBvZiBwYXJyaXNoZXMgYnkgdGhlaXIgZGVjaXNpb24gdHJlZSBub2RlIChkZW5vdGVkIGJ5IGNvbG91ciksIHdlIGhhdmUgYWxzbyBkZWNyZWFzZWQgdGhlIGFscGhhIGZvciBwYXJyaXNoZXMgd2hlcmUgdGhlcmUgYXJlIGFscmVhZHkgb3JnYW5pc2F0aW9ucyBwcmVzZW50LCBtZWFuaW5nIHRoYXQgdGhleSBhcHBlYXIgbW9yZSB0cmFuc3BhcmVudC4gTG9va2luZyBhdCBbNF0gYW5kIFs1XSwgd2UgY2FuIHNlZSB0aGUgcGFycmlzaGVzIHRoYXQgY29uZm9ybSB0byB0aGUgdGhlIFZlbmV6dWVsYSBDb3N0YWwgUmFuZ2UgYW5kIHRoZSBWZW5lenVlbGFuIEFuZGVzLCB3aGVyZSBtb3N0IG9mIHRoZSBjb3VudHJ5J3MgcG9wdWxhdGlvbiBpcyBjb25jZW50cmF0ZWQ7IGFzIGEgcmVtaW5kZXIsIHBhcnJpc2hlcyBpbiBub2RlIFs1XSBhcmUgZXhjZWxsZW50IGNhbmRpZGF0ZXMgZm9yIGV4cGFuc2lvbi4gDQoNCldlIGFsc28gc2VlIHRocmVlIGxhcmdlIGNsdXN0ZXJzIG9mIHBhcnJpc2hlcyBmcm9tIG5vZGUgWzddIC0tIHRoZSBwb29yZXN0IGFuZCBtb3N0LXNwYXJzZWx5IHBvcHVsYXRlZCBhcmVhcyAtLSBpbiBBbWF6b25hcyBhbmQgQm9saXZhciAoYXQgdGhlIGJvdHRvbSBvZiB0aGUgbWFwKSwgaW4gRGVsdGEgQW1hY3VybyAoYXQgdGhlIGV4dHJlbWUgcmlnaHQpIGFuZCBpbiBMYXJhIGFuZCBGYWxjb24gKHRvcC1sZWZ0KS4gRG91YmxlLWNsaWNrIG9uIGVhY2ggbGVnZW5kIGl0ZW0gdG8gdG9nZ2xlIHRoZSB2aWV3LiAgDQoNCjxicj4NCg0KKiBQYXJ0IDUgYW5uZXg6IEFkZGl0aW9uYWwgbm90ZXMgb24gdHJlZTEsIHdoaWNoIHdhcyBub3Qgc2VsZWN0ZWQgLS0gdW5oaWRlIGNvZGUgdG8gc2VlDQoNCmBgYHtyIHRyZWUxLW5vdGVzLCByZXN1bHRzPUZBTFNFfQ0KIyB0aGUgbWFpbiBwcm9ibGVtIEkgc2VlIGlzIHRoYXQgZWFjaCBvZiB0aGUgbGVhdmVzIGhhcyBsaXR0bGUgdmFyaWFuY2UgaW4gdGVybXMgb2YgcG92ZXJ0eSBpbmNpZGVuY2UNCiMgYnV0IGxldCBtZSBrbm93IGlmIHlvdSB3YW50IG1hcHMgb3IgcHJvZHVjdHMgZm9jdXNlZCBvbiB0aGlzIHRyZWUsIGl0J3MgcHJldHR5IGVhc3kgdG8gZG8uIFsxNV0gaXMgdmVyeSwgdmVyeSBhdHRyYWN0aXZlLiBNYXliZSBJIGNhbiBkbyBzb21ldGhpbmcgd2l0aCBpdC4gIA0KDQojIDYgaXMgZGVuc2UsIHVyYmFuIGFuZCBoaWdoZXN0IG9wZXJhdGlvbmFsIHByZXNlbmNlLA0KIyAyIGlzIGp1c3QgdG9vIGJpZy4gODAwIHBhcnJpc2hlcyBpcyBqdXN0IHRvbyBtYW55LiBUaGUgbG93IGVuZCBpcyBkaXN0aW5ndWlzaGVkIG11Y2ggYmV0dGVyIGluIHRyZWUzDQojIDE0IGlzIGp1c3QgcmljaCwgdXJiYW4gYW5kIG5vdCBhIHByaW9yaXR5LiBJdCdzIGFsc28gYSByZWFsbHkgc21hbGwgbGVhZi4gIA0KIyAxNSBpcyBhY3R1YWxseSBhIHJlYWxseSBnb29kIGxlYWYgLS0gcmVhbGx5IGhpZ2ggbmNfcGVyX3BhcnIsIGZldyBwYXJyaXNoZXMsIHZlcnkgZGVuc2UsIHZlcnkgdXJiYW4gYW5kIDQyJSBwb29yIGFuZCBzdWNoIGFuIGltbWVuc2VseSBsb3cgY292ZXJhZ2UgcGVyY2VudC4gR29vZCBsb3ctaGFuZ2luZyBmcnVpdC4gSSBhbG1vc3Qgd2FudCB0byBrZWVwIHRyZWUxIGp1c3QgYmVjYXVzZSBvZiB0aGlzIGxlYWYuIE1heWJlIEkgd2lsbCBtYWtlIG9uZSBtYXAganVzdCBmb3IgdGhpcy4gNTksNTA4IG5jX3Blcl9wYXJyIGlzIG1hc3NpdmUuIA0KDQpwYXJyMCAlPiUgDQogIGdyb3VwX2J5KHJ1bGUxKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyX25vX2JlbiA9IG5fZGlzdGluY3QocGNvZGUzW2JlbmVmaWNpYXJpb3MgPT0gMF0pLCANCiAgICAgICAgICAgIGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICBiZW5fcGVyX3BhcnIgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBuKCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSBzdW0obm90X3JlYWNoZWQpLA0KICAgICAgICAgICAgbnJfcGVyX3BhcnIgPSBzdW0obm90X3JlYWNoZWQpIC8gbigpLA0KICAgICAgICAgICAgbnJfcGVyX211biA9IHN1bShub3RfcmVhY2hlZCkgLyBuX2Rpc3RpbmN0KHBjb2RlMiksIA0KICAgICAgICAgICAgYXZnX29yZ19jb3VudCA9IG1lYW4ob3JnX2NvdW50KSwNCiAgICAgICAgICAgIGNvdmVyYWdlX3BlcmNlbnQgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBzdW0ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgcGVyY2VudF9wb2JyZSA9IHN1bShwb2JfcG9icmUpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwNCiAgICAgICAgICAgIHBlcmNlbnRfdXJiYW5hID0gc3VtKHBvYl91cmJhbmEpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwNCiAgICAgICAgICAgIGRlbnNpZGFkX3BwbF9rbTIgPSBzdW0ocG9ibGFjaW9uXzIwMTkpIC8gc3VtKGFyZWFfa20yLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgcGFycm9xdWlhcyA9IG4oKSwNCiAgICAgICAgICAgIG11bmljaXBpb3MgPSBuX2Rpc3RpbmN0KHBjb2RlMiksDQogICAgICAgICAgICBwYXJyX3Blcl9tdW4gPSBuKCkgLyBuX2Rpc3RpbmN0KHBjb2RlMikpICU+JSANCiAgZ2F0aGVyKGtleSA9IHZhcmlhYmxlLCB2YWx1ZSA9IHZhbHVlLCAyOm5jb2woLikpICU+JSANCiAgc3ByZWFkXyhrZXkgPSBuYW1lcyguKVsxXSwgdmFsdWUgPSAndmFsdWUnKSAlPiUgDQogIGFycmFuZ2UoZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJub3RfcmVhY2hlZCIsICJucl9wZXJfcGFyciIsICJucl9wZXJfbXVuIiwgImJlbmVmaWNpYXJpb3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmVuX3Blcl9wYXJyIiwgICJhdmdfb3JnX2NvdW50IiwgImNvdmVyYWdlX3BlcmNlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGVyY2VudF9wb2JyZSIsICJwZXJjZW50X3VyYmFuYSIsICJkZW5zaWRhZF9wcGxfa20yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwYXJyb3F1aWFzIiwgInBhcnJfbm9fYmVuIiwgIm11bmljaXBpb3MiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBhcnJfcGVyX211biIpKSkgJT4lICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIpDQoNCmBgYA0KDQoNCjxicj48YnI+DQoNCg0KDQojIyA2LiBSZWZlcmVuY2UgVGFibGUgDQpfdHlwZSBvciB1c2Ugc2xpZGVyIHRvIGZpbHRlciBieSBjYXRlZ29yaWVzIG9yIHZhbHVlcztfIA0KX3VzZSBhcnJvd3MgdG8gc29ydDsgdGFibGUgcHJlbGltaW5hcmlseSBhcnJhbmdlZCBpbiBkZXNjZW5kaW5nIG9yZGVyIG9mIG51bWJlciBvZiBub3QgcmVhY2hlZF8NCg0KYGBge3J9DQpwYXJyMCAlPiUNCiAgc2VsZWN0KC1wZXJjZW50X3RvdGFsX2JlbikgJT4lIA0KICBtdXRhdGUoc2VjdG9yX2NvdW50ID0gcm93U3VtcyhzZWxlY3QoLiwgZW5kc193aXRoKCJfYmVuIikpIT0wKSkgJT4lIA0KICBtdXRhdGUoZWR1Y2FjaW9uX29ubHkgPSBpZmVsc2UoZWR1Y2FjaW9uX2JlbiA+IDAsICJlZHVjYWNpb24iLCAiIiksDQogICAgICAgICBudXRyaWNpb25fb25seSA9IGlmZWxzZShudXRyaWNpb25fYmVuID4gMCwgIm51dHJpY2lvbiIsICIiKSwNCiAgICAgICAgIHNhbHVkX29ubHkgPSBpZmVsc2Uoc2FsdWRfYmVuID4gMCwgInNhbHVkIiwgICIiKSwNCiAgICAgICAgIHdhc2hfb25seSA9IGlmZWxzZSh3YXNoX2JlbiA+IDAsICJ3YXNoIiwgIiIpLA0KICAgICAgICAgcHJvdGVjY2lvbl9vbmx5ID0gaWZlbHNlKHByb3RlY2Npb25fYmVuID4gMCwgInByb3RlY2Npb24iLCAiIiksDQogICAgICAgICBzZWN0b3JzX3ByZXNlbnQgPSBzdHJfdHJpbShwYXN0ZTAoZWR1Y2FjaW9uX29ubHksICIgIiwgbnV0cmljaW9uX29ubHksICIgIiwgcHJvdGVjY2lvbl9vbmx5LCAiICIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX29ubHksICIgIiwgd2FzaF9vbmx5KSkpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocG9iX3BvYnJlLCBub3RfcmVhY2hlZCwgb3JnX2NvdW50LCBiZW5lZmljaWFyaW9zKSwgfihyb3VuZCguLCBkaWdpdHMgPSAwKSkpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocGVyY2VudF9wb2JyZSwgcGVyY2VudF91cmJhbmEpLCB+KHJvdW5kKC4sIGRpZ2l0cyA9IDIpKSkgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBtdW5pY2lwaW8sIHBhcnJvcXVpYSwgIA0KICAgICAgICAgcGVyY2VudF9wb2JyZSwgcGVyY2VudF91cmJhbmEsIG5vdF9yZWFjaGVkLCBiZW5lZmljaWFyaW9zLCB0cmVlX25vZGUgPSBydWxlMywNCiAgICAgICAgIG9yZ19jb3VudCwgc2VjdG9yX2NvdW50LCBzZWN0b3JzX3ByZXNlbnQsIHBjb2RlMykgJT4lIA0KICBhcnJhbmdlKGRlc2Mobm90X3JlYWNoZWQpKSAlPiUgDQogICMgdGhlIGpzIGlzIGFkanVzdGluZyB0aGUgZm9udCBzaXplIGZvciB0aGUgd2hvbGUgY29udGFpbmVyIC0tIHRoZXJlIGRvZXNuJ3Qgc2VlbSB0byBiZSBhbm90aGVyIHdheQ0KICBkYXRhdGFibGUoZmlsdGVyID0gInRvcCIsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwgc2Nyb2xsWCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdENvbXBsZXRlID0gaHRtbHdpZGdldHM6OkpTKA0KICAgICAgICAgICJmdW5jdGlvbihzZXR0aW5ncywganNvbikgeyIsDQogICAgICAgICAgcGFzdGUwKCIkKHRoaXMuYXBpKCkudGFibGUoKS5jb250YWluZXIoKSkuY3NzKHsnZm9udC1zaXplJzogJyIsICI4LjVwdCIsICInfSk7IiksDQogICAgICAgICAgIn0iKQ0KICAgICAgICkgDQogICAgICkgDQpgYGANCg==